mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-03 05:26:07 +00:00
refactor: structures & folders 2
This commit is contained in:
parent
d1d0a1ce76
commit
cc7a5848eb
51
structures/channels/BaseChannel.ts
Normal file
51
structures/channels/BaseChannel.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { DiscordChannel } from "../../vendor/external.ts";
|
||||
import type TextChannel from "./TextChannel.ts";
|
||||
import type VoiceChannel from "./VoiceChannel.ts";
|
||||
import type DMChannel from "./DMChannel.ts";
|
||||
import type NewsChannel from "./NewsChannel.ts";
|
||||
import type ThreadChannel from "./ThreadChannel.ts";
|
||||
import { ChannelTypes } from "../../vendor/external.ts";
|
||||
import { textBasedChannels } from "./TextChannel.ts";
|
||||
|
||||
export abstract class BaseChannel implements Model {
|
||||
constructor(session: Session, data: DiscordChannel) {
|
||||
this.id = data.id;
|
||||
this.session = session;
|
||||
this.name = data.name;
|
||||
this.type = data.type;
|
||||
}
|
||||
readonly id: Snowflake;
|
||||
readonly session: Session;
|
||||
|
||||
name?: string;
|
||||
type: ChannelTypes;
|
||||
|
||||
isText(): this is TextChannel {
|
||||
return textBasedChannels.includes(this.type);
|
||||
}
|
||||
|
||||
isVoice(): this is VoiceChannel {
|
||||
return this.type === ChannelTypes.GuildVoice;
|
||||
}
|
||||
|
||||
isDM(): this is DMChannel {
|
||||
return this.type === ChannelTypes.DM;
|
||||
}
|
||||
|
||||
isNews(): this is NewsChannel {
|
||||
return this.type === ChannelTypes.GuildNews;
|
||||
}
|
||||
|
||||
isThread(): this is ThreadChannel {
|
||||
return this.type === ChannelTypes.GuildPublicThread || this.type === ChannelTypes.GuildPrivateThread;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<#${this.id}>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseChannel;
|
39
structures/channels/ChannelFactory.ts
Normal file
39
structures/channels/ChannelFactory.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { DiscordChannel } from "../../vendor/external.ts";
|
||||
import { ChannelTypes } from "../../vendor/external.ts";
|
||||
import { textBasedChannels } from "./TextChannel.ts";
|
||||
import TextChannel from "./TextChannel.ts";
|
||||
import VoiceChannel from "./VoiceChannel.ts";
|
||||
import DMChannel from "./DMChannel.ts";
|
||||
import NewsChannel from "./NewsChannel.ts";
|
||||
import ThreadChannel from "./ThreadChannel.ts";
|
||||
|
||||
export type Channel =
|
||||
| TextChannel
|
||||
| VoiceChannel
|
||||
| DMChannel
|
||||
| NewsChannel
|
||||
| ThreadChannel;
|
||||
|
||||
export class ChannelFactory {
|
||||
static from(session: Session, channel: DiscordChannel): Channel {
|
||||
switch (channel.type) {
|
||||
case ChannelTypes.GuildPublicThread:
|
||||
case ChannelTypes.GuildPrivateThread:
|
||||
return new ThreadChannel(session, channel, channel.guild_id!);
|
||||
case ChannelTypes.GuildNews:
|
||||
return new NewsChannel(session, channel, channel.guild_id!);
|
||||
case ChannelTypes.DM:
|
||||
return new DMChannel(session, channel);
|
||||
case ChannelTypes.GuildVoice:
|
||||
return new VoiceChannel(session, channel, channel.guild_id!);
|
||||
default:
|
||||
if (textBasedChannels.includes(channel.type)) {
|
||||
return new TextChannel(session, channel);
|
||||
}
|
||||
throw new Error("Channel was not implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ChannelFactory;
|
39
structures/channels/DMChannel.ts
Normal file
39
structures/channels/DMChannel.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { ChannelTypes, DiscordChannel } from "../../vendor/external.ts";
|
||||
import TextChannel from "./TextChannel.ts";
|
||||
import BaseChannel from "./BaseChannel.ts";
|
||||
import User from "../User.ts";
|
||||
import * as Routes from "../../util/Routes.ts";
|
||||
|
||||
export class DMChannel extends BaseChannel implements Model {
|
||||
constructor(session: Session, data: DiscordChannel) {
|
||||
super(session, data);
|
||||
this.user = new User(this.session, data.recipents!.find((r) => r.id !== this.session.botId)!);
|
||||
this.type = data.type as ChannelTypes.DM | ChannelTypes.GroupDm;
|
||||
if (data.last_message_id) {
|
||||
this.lastMessageId = data.last_message_id;
|
||||
}
|
||||
}
|
||||
|
||||
override type: ChannelTypes.DM | ChannelTypes.GroupDm;
|
||||
user: User;
|
||||
lastMessageId?: Snowflake;
|
||||
|
||||
async close() {
|
||||
const channel = await this.session.rest.runMethod<DiscordChannel>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.CHANNEL(this.id),
|
||||
);
|
||||
|
||||
return new DMChannel(this.session, channel);
|
||||
}
|
||||
}
|
||||
|
||||
TextChannel.applyTo(DMChannel);
|
||||
|
||||
export interface DMChannel extends Omit<TextChannel, "type">, Omit<BaseChannel, "type"> {}
|
||||
|
||||
export default DMChannel;
|
70
structures/channels/GuildChannel.ts
Normal file
70
structures/channels/GuildChannel.ts
Normal file
@ -0,0 +1,70 @@
|
||||
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 } from "../../vendor/external.ts";
|
||||
import BaseChannel from "./BaseChannel.ts";
|
||||
import Invite from "../Invite.ts";
|
||||
import * as Routes from "../../util/Routes.ts";
|
||||
|
||||
/**
|
||||
* Represent the options object to create a Thread Channel
|
||||
* @link https://discord.com/developers/docs/resources/channel#start-thread-without-message
|
||||
*/
|
||||
export interface ThreadCreateOptions {
|
||||
name: string;
|
||||
autoArchiveDuration: 60 | 1440 | 4320 | 10080;
|
||||
type: 10 | 11 | 12;
|
||||
invitable?: boolean;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export class GuildChannel extends BaseChannel implements Model {
|
||||
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
|
||||
super(session, data);
|
||||
this.type = data.type as number;
|
||||
this.guildId = guildId;
|
||||
this.position = data.position;
|
||||
data.topic ? this.topic = data.topic : null;
|
||||
data.parent_id ? this.parentId = data.parent_id : undefined;
|
||||
}
|
||||
|
||||
override type: Exclude<ChannelTypes, ChannelTypes.DM | ChannelTypes.GroupDm>;
|
||||
guildId: Snowflake;
|
||||
topic?: string;
|
||||
position?: number;
|
||||
parentId?: Snowflake;
|
||||
|
||||
async fetchInvites(): Promise<Invite[]> {
|
||||
const invites = await this.session.rest.runMethod<DiscordInviteMetadata[]>(
|
||||
this.session.rest,
|
||||
"GET",
|
||||
Routes.CHANNEL_INVITES(this.id),
|
||||
);
|
||||
|
||||
return invites.map((invite) => new Invite(this.session, invite));
|
||||
}
|
||||
|
||||
/*
|
||||
async createThread(options: ThreadCreateOptions): Promise<ThreadChannel> {
|
||||
const thread = await this.session.rest.runMethod<DiscordChannel>(
|
||||
this.session.rest,
|
||||
"POST",
|
||||
Routes.CHANNEL_CREATE_THREAD(this.id),
|
||||
options,
|
||||
);
|
||||
return new ThreadChannel(this.session, thread, this.guildId);
|
||||
}*/
|
||||
|
||||
async delete(reason?: string) {
|
||||
await this.session.rest.runMethod<DiscordChannel>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.CHANNEL(this.id),
|
||||
{
|
||||
reason,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GuildChannel;
|
31
structures/channels/NewsChannel.ts
Normal file
31
structures/channels/NewsChannel.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { ChannelTypes, DiscordChannel } from "../../vendor/external.ts";
|
||||
import GuildChannel from "./GuildChannel.ts";
|
||||
import Message from "../Message.ts";
|
||||
import TextChannel from "./TextChannel.ts";
|
||||
|
||||
export class NewsChannel extends GuildChannel {
|
||||
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
|
||||
super(session, data, guildId);
|
||||
this.type = data.type as ChannelTypes.GuildNews;
|
||||
this.defaultAutoArchiveDuration = data.default_auto_archive_duration;
|
||||
}
|
||||
|
||||
override type: ChannelTypes.GuildNews;
|
||||
defaultAutoArchiveDuration?: number;
|
||||
|
||||
crosspostMessage(messageId: Snowflake): Promise<Message> {
|
||||
return Message.prototype.crosspost.call({ id: messageId, channelId: this.id, session: this.session });
|
||||
}
|
||||
|
||||
get publishMessage() {
|
||||
return this.crosspostMessage;
|
||||
}
|
||||
}
|
||||
|
||||
TextChannel.applyTo(NewsChannel);
|
||||
|
||||
export interface NewsChannel extends TextChannel, GuildChannel {}
|
||||
|
||||
export default NewsChannel;
|
221
structures/channels/TextChannel.ts
Normal file
221
structures/channels/TextChannel.ts
Normal file
@ -0,0 +1,221 @@
|
||||
// deno-lint-ignore-file ban-types
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { GetMessagesOptions, GetReactions } from "../../util/Routes.ts";
|
||||
import type {
|
||||
DiscordChannel,
|
||||
DiscordInvite,
|
||||
DiscordMessage,
|
||||
DiscordWebhook,
|
||||
TargetTypes,
|
||||
} from "../../vendor/external.ts";
|
||||
import type { CreateMessage, EditMessage, ReactionResolvable } from "../Message.ts";
|
||||
import { ChannelTypes } from "../../vendor/external.ts";
|
||||
import { urlToBase64 } from "../../util/urlToBase64.ts";
|
||||
import Message from "../Message.ts";
|
||||
import Invite from "../Invite.ts";
|
||||
import Webhook from "../Webhook.ts";
|
||||
import * as Routes from "../../util/Routes.ts";
|
||||
|
||||
/**
|
||||
* Represents the options object to create an invitation
|
||||
* @link https://discord.com/developers/docs/resources/channel#create-channel-invite-json-params
|
||||
*/
|
||||
export interface DiscordInviteOptions {
|
||||
maxAge?: number;
|
||||
maxUses?: number;
|
||||
unique?: boolean;
|
||||
temporary: boolean;
|
||||
reason?: string;
|
||||
targetType?: TargetTypes;
|
||||
targetUserId?: Snowflake;
|
||||
targetApplicationId?: Snowflake;
|
||||
}
|
||||
|
||||
export interface CreateWebhook {
|
||||
name: string;
|
||||
avatar?: string;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export const textBasedChannels = [
|
||||
ChannelTypes.DM,
|
||||
ChannelTypes.GroupDm,
|
||||
ChannelTypes.GuildPrivateThread,
|
||||
ChannelTypes.GuildPublicThread,
|
||||
ChannelTypes.GuildNews,
|
||||
ChannelTypes.GuildText,
|
||||
];
|
||||
|
||||
export type TextBasedChannels =
|
||||
| ChannelTypes.DM
|
||||
| ChannelTypes.GroupDm
|
||||
| ChannelTypes.GuildPrivateThread
|
||||
| ChannelTypes.GuildPublicThread
|
||||
| ChannelTypes.GuildNews
|
||||
| ChannelTypes.GuildText;
|
||||
|
||||
export class TextChannel {
|
||||
constructor(session: Session, data: DiscordChannel) {
|
||||
this.session = session;
|
||||
this.id = data.id;
|
||||
this.name = data.name;
|
||||
this.type = data.type as number;
|
||||
this.rateLimitPerUser = data.rate_limit_per_user ?? 0;
|
||||
this.nsfw = !!data.nsfw ?? false;
|
||||
|
||||
if (data.last_message_id) {
|
||||
this.lastMessageId = data.last_message_id;
|
||||
}
|
||||
|
||||
if (data.last_pin_timestamp) {
|
||||
this.lastPinTimestamp = data.last_pin_timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
readonly session: Session;
|
||||
readonly id: Snowflake;
|
||||
name?: string;
|
||||
type: TextBasedChannels;
|
||||
lastMessageId?: Snowflake;
|
||||
lastPinTimestamp?: string;
|
||||
rateLimitPerUser: number;
|
||||
nsfw: boolean;
|
||||
|
||||
/**
|
||||
* Mixin
|
||||
*/
|
||||
static applyTo(klass: Function) {
|
||||
klass.prototype.fetchPins = TextChannel.prototype.fetchPins;
|
||||
klass.prototype.createInvite = TextChannel.prototype.createInvite;
|
||||
klass.prototype.fetchMessages = TextChannel.prototype.fetchMessages;
|
||||
klass.prototype.sendTyping = TextChannel.prototype.sendTyping;
|
||||
klass.prototype.pinMessage = TextChannel.prototype.pinMessage;
|
||||
klass.prototype.unpinMessage = TextChannel.prototype.unpinMessage;
|
||||
klass.prototype.addReaction = TextChannel.prototype.addReaction;
|
||||
klass.prototype.removeReaction = TextChannel.prototype.removeReaction;
|
||||
klass.prototype.removeReactionEmoji = TextChannel.prototype.removeReactionEmoji;
|
||||
klass.prototype.nukeReactions = TextChannel.prototype.nukeReactions;
|
||||
klass.prototype.fetchReactions = TextChannel.prototype.fetchReactions;
|
||||
klass.prototype.sendMessage = TextChannel.prototype.sendMessage;
|
||||
klass.prototype.editMessage = TextChannel.prototype.editMessage;
|
||||
klass.prototype.createWebhook = TextChannel.prototype.createWebhook;
|
||||
}
|
||||
|
||||
async fetchPins(): Promise<Message[] | []> {
|
||||
const messages = await this.session.rest.runMethod<DiscordMessage[]>(
|
||||
this.session.rest,
|
||||
"GET",
|
||||
Routes.CHANNEL_PINS(this.id),
|
||||
);
|
||||
return messages[0] ? messages.map((x: DiscordMessage) => new Message(this.session, x)) : [];
|
||||
}
|
||||
|
||||
async createInvite(options?: DiscordInviteOptions) {
|
||||
const invite = await this.session.rest.runMethod<DiscordInvite>(
|
||||
this.session.rest,
|
||||
"POST",
|
||||
Routes.CHANNEL_INVITES(this.id),
|
||||
options
|
||||
? {
|
||||
max_age: options.maxAge,
|
||||
max_uses: options.maxUses,
|
||||
temporary: options.temporary,
|
||||
unique: options.unique,
|
||||
target_type: options.targetType,
|
||||
target_user_id: options.targetUserId,
|
||||
target_application_id: options.targetApplicationId,
|
||||
}
|
||||
: {},
|
||||
);
|
||||
|
||||
return new Invite(this.session, invite);
|
||||
}
|
||||
|
||||
async fetchMessages(options?: GetMessagesOptions): Promise<Message[] | []> {
|
||||
if (options?.limit! > 100) throw Error("Values must be between 0-100");
|
||||
const messages = await this.session.rest.runMethod<DiscordMessage[]>(
|
||||
this.session.rest,
|
||||
"GET",
|
||||
Routes.CHANNEL_MESSAGES(this.id, options),
|
||||
);
|
||||
return messages[0] ? messages.map((x) => new Message(this.session, x)) : [];
|
||||
}
|
||||
|
||||
async sendTyping() {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"POST",
|
||||
Routes.CHANNEL_TYPING(this.id),
|
||||
);
|
||||
}
|
||||
|
||||
async pinMessage(messageId: Snowflake) {
|
||||
await Message.prototype.pin.call({ id: messageId, channelId: this.id, session: this.session });
|
||||
}
|
||||
|
||||
async unpinMessage(messageId: Snowflake) {
|
||||
await Message.prototype.unpin.call({ id: messageId, channelId: this.id, session: this.session });
|
||||
}
|
||||
|
||||
async addReaction(messageId: Snowflake, reaction: ReactionResolvable) {
|
||||
await Message.prototype.addReaction.call(
|
||||
{ channelId: this.id, id: messageId, session: this.session },
|
||||
reaction,
|
||||
);
|
||||
}
|
||||
|
||||
async removeReaction(messageId: Snowflake, reaction: ReactionResolvable, options?: { userId: Snowflake }) {
|
||||
await Message.prototype.removeReaction.call(
|
||||
{ channelId: this.id, id: messageId, session: this.session },
|
||||
reaction,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
async removeReactionEmoji(messageId: Snowflake, reaction: ReactionResolvable) {
|
||||
await Message.prototype.removeReactionEmoji.call(
|
||||
{ channelId: this.id, id: messageId, session: this.session },
|
||||
reaction,
|
||||
);
|
||||
}
|
||||
|
||||
async nukeReactions(messageId: Snowflake) {
|
||||
await Message.prototype.nukeReactions.call({ channelId: this.id, id: messageId });
|
||||
}
|
||||
|
||||
async fetchReactions(messageId: Snowflake, reaction: ReactionResolvable, options?: GetReactions) {
|
||||
const users = await Message.prototype.fetchReactions.call(
|
||||
{ channelId: this.id, id: messageId, session: this.session },
|
||||
reaction,
|
||||
options,
|
||||
);
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
sendMessage(options: CreateMessage) {
|
||||
return Message.prototype.reply.call({ channelId: this.id, session: this.session }, options);
|
||||
}
|
||||
|
||||
editMessage(messageId: Snowflake, options: EditMessage) {
|
||||
return Message.prototype.edit.call({ channelId: this.id, id: messageId, session: this.session }, options);
|
||||
}
|
||||
|
||||
async createWebhook(options: CreateWebhook) {
|
||||
const webhook = await this.session.rest.runMethod<DiscordWebhook>(
|
||||
this.session.rest,
|
||||
"POST",
|
||||
Routes.CHANNEL_WEBHOOKS(this.id),
|
||||
{
|
||||
name: options.name,
|
||||
avatar: options.avatar ? urlToBase64(options.avatar) : undefined,
|
||||
reason: options.reason,
|
||||
},
|
||||
);
|
||||
|
||||
return new Webhook(this.session, webhook);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextChannel;
|
35
structures/channels/ThreadChannel.ts
Normal file
35
structures/channels/ThreadChannel.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { ChannelTypes, DiscordChannel } from "../../vendor/external.ts";
|
||||
import GuildChannel from "./GuildChannel.ts";
|
||||
import TextChannel from "./TextChannel.ts";
|
||||
|
||||
export class ThreadChannel extends GuildChannel implements Model {
|
||||
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
|
||||
super(session, data, guildId);
|
||||
this.type = data.type as number;
|
||||
this.archived = !!data.thread_metadata?.archived;
|
||||
this.archiveTimestamp = data.thread_metadata?.archive_timestamp;
|
||||
this.autoArchiveDuration = data.thread_metadata?.auto_archive_duration;
|
||||
this.locked = !!data.thread_metadata?.locked;
|
||||
this.messageCount = data.message_count;
|
||||
this.memberCount = data.member_count;
|
||||
this.ownerId = data.owner_id;
|
||||
}
|
||||
|
||||
override type: ChannelTypes.GuildNewsThread | ChannelTypes.GuildPrivateThread | ChannelTypes.GuildPublicThread;
|
||||
archived?: boolean;
|
||||
archiveTimestamp?: string;
|
||||
autoArchiveDuration?: number;
|
||||
locked?: boolean;
|
||||
messageCount?: number;
|
||||
memberCount?: number;
|
||||
ownerId?: Snowflake;
|
||||
}
|
||||
|
||||
TextChannel.applyTo(ThreadChannel);
|
||||
|
||||
export interface ThreadChannel extends Omit<GuildChannel, "type">, Omit<TextChannel, "type"> {}
|
||||
|
||||
export default ThreadChannel;
|
60
structures/channels/VoiceChannel.ts
Normal file
60
structures/channels/VoiceChannel.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { DiscordChannel, VideoQualityModes } from "../../vendor/external.ts";
|
||||
import { GatewayOpcodes } from "../../vendor/external.ts";
|
||||
import { calculateShardId } from "../../vendor/gateway/calculateShardId.ts";
|
||||
import GuildChannel from "./GuildChannel.ts";
|
||||
|
||||
/**
|
||||
* @link https://discord.com/developers/docs/topics/gateway#update-voice-state
|
||||
*/
|
||||
export interface UpdateVoiceState {
|
||||
guildId: string;
|
||||
channelId?: string;
|
||||
selfMute: boolean;
|
||||
selfDeaf: boolean;
|
||||
}
|
||||
|
||||
export class VoiceChannel extends GuildChannel {
|
||||
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
|
||||
super(session, data, guildId);
|
||||
this.bitRate = data.bitrate;
|
||||
this.userLimit = data.user_limit ?? 0;
|
||||
this.videoQuality = data.video_quality_mode;
|
||||
this.nsfw = !!data.nsfw;
|
||||
|
||||
if (data.rtc_region) {
|
||||
this.rtcRegion = data.rtc_region;
|
||||
}
|
||||
}
|
||||
bitRate?: number;
|
||||
userLimit: number;
|
||||
rtcRegion?: Snowflake;
|
||||
|
||||
videoQuality?: VideoQualityModes;
|
||||
nsfw: boolean;
|
||||
|
||||
/**
|
||||
* This function was gathered from Discordeno it may not work
|
||||
*/
|
||||
async connect(options?: UpdateVoiceState) {
|
||||
const shardId = calculateShardId(this.session.gateway, BigInt(super.guildId));
|
||||
const shard = this.session.gateway.manager.shards.get(shardId);
|
||||
|
||||
if (!shard) {
|
||||
throw new Error(`Shard (id: ${shardId} not found`);
|
||||
}
|
||||
|
||||
await shard.send({
|
||||
op: GatewayOpcodes.VoiceStateUpdate,
|
||||
d: {
|
||||
guild_id: super.guildId,
|
||||
channel_id: super.id,
|
||||
self_mute: Boolean(options?.selfMute),
|
||||
self_deaf: options?.selfDeaf ?? true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default VoiceChannel;
|
55
structures/guilds/AnonymousGuild.ts
Normal file
55
structures/guilds/AnonymousGuild.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { DiscordGuild, GuildNsfwLevel, VerificationLevels } from "../../vendor/external.ts";
|
||||
import type { ImageFormat, ImageSize } from "../../util/shared/images.ts";
|
||||
import { iconBigintToHash, iconHashToBigInt } from "../../util/hash.ts";
|
||||
import { formatImageUrl } from "../../util/shared/images.ts";
|
||||
import BaseGuild from "./BaseGuild.ts";
|
||||
import * as Routes from "../../util/Routes.ts";
|
||||
|
||||
export class AnonymousGuild extends BaseGuild implements Model {
|
||||
constructor(session: Session, data: Partial<DiscordGuild>); // TODO: Improve this type (name and id are required)
|
||||
constructor(session: Session, data: DiscordGuild) {
|
||||
super(session, data);
|
||||
|
||||
this.splashHash = data.splash ? iconHashToBigInt(data.splash) : undefined;
|
||||
this.bannerHash = data.banner ? iconHashToBigInt(data.banner) : undefined;
|
||||
|
||||
this.verificationLevel = data.verification_level;
|
||||
this.vanityUrlCode = data.vanity_url_code ? data.vanity_url_code : undefined;
|
||||
this.nsfwLevel = data.nsfw_level;
|
||||
this.description = data.description ? data.description : undefined;
|
||||
this.premiumSubscriptionCount = data.premium_subscription_count;
|
||||
}
|
||||
|
||||
splashHash?: bigint;
|
||||
bannerHash?: bigint;
|
||||
|
||||
verificationLevel: VerificationLevels;
|
||||
vanityUrlCode?: string;
|
||||
nsfwLevel: GuildNsfwLevel;
|
||||
description?: string;
|
||||
premiumSubscriptionCount?: number;
|
||||
|
||||
splashUrl(options: { size?: ImageSize; format?: ImageFormat } = { size: 128 }) {
|
||||
if (this.splashHash) {
|
||||
return formatImageUrl(
|
||||
Routes.GUILD_SPLASH(this.id, iconBigintToHash(this.splashHash)),
|
||||
options.size,
|
||||
options.format,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bannerUrl(options: { size?: ImageSize; format?: ImageFormat } = { size: 128 }) {
|
||||
if (this.bannerHash) {
|
||||
return formatImageUrl(
|
||||
Routes.GUILD_BANNER(this.id, iconBigintToHash(this.bannerHash)),
|
||||
options.size,
|
||||
options.format,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AnonymousGuild;
|
41
structures/guilds/BaseGuild.ts
Normal file
41
structures/guilds/BaseGuild.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { DiscordGuild, GuildFeatures } from "../../vendor/external.ts";
|
||||
import { Snowflake } from "../../util/Snowflake.ts";
|
||||
import { iconHashToBigInt } from "../../util/hash.ts";
|
||||
|
||||
/**
|
||||
* Class for {@link Guild} and {@link AnonymousGuild}
|
||||
*/
|
||||
export abstract class BaseGuild implements Model {
|
||||
constructor(session: Session, data: DiscordGuild) {
|
||||
this.session = session;
|
||||
this.id = data.id;
|
||||
|
||||
this.name = data.name;
|
||||
this.iconHash = data.icon ? iconHashToBigInt(data.icon) : undefined;
|
||||
|
||||
this.features = data.features;
|
||||
}
|
||||
|
||||
readonly session: Session;
|
||||
readonly id: Snowflake;
|
||||
|
||||
name: string;
|
||||
iconHash?: bigint;
|
||||
features: GuildFeatures[];
|
||||
|
||||
get createdTimestamp() {
|
||||
return Snowflake.snowflakeToTimestamp(this.id);
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseGuild;
|
367
structures/guilds/Guild.ts
Normal file
367
structures/guilds/Guild.ts
Normal file
@ -0,0 +1,367 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type {
|
||||
DiscordEmoji,
|
||||
DiscordGuild,
|
||||
DiscordInviteMetadata,
|
||||
DiscordMemberWithUser,
|
||||
DiscordRole,
|
||||
} from "../../vendor/external.ts";
|
||||
import type { GetInvite } from "../../util/Routes.ts";
|
||||
import {
|
||||
DefaultMessageNotificationLevels,
|
||||
ExplicitContentFilterLevels,
|
||||
VerificationLevels,
|
||||
} from "../../vendor/external.ts";
|
||||
import { iconBigintToHash, iconHashToBigInt } from "../../util/hash.ts";
|
||||
import { urlToBase64 } from "../../util/urlToBase64.ts";
|
||||
import Member from "../Member.ts";
|
||||
import BaseGuild from "./BaseGuild.ts";
|
||||
import Role from "../Role.ts";
|
||||
import GuildEmoji from "../GuildEmoji.ts";
|
||||
import Invite from "../Invite.ts";
|
||||
import * as Routes from "../../util/Routes.ts";
|
||||
|
||||
export interface CreateRole {
|
||||
name?: string;
|
||||
color?: number;
|
||||
iconHash?: string | bigint;
|
||||
unicodeEmoji?: string;
|
||||
hoist?: boolean;
|
||||
mentionable?: boolean;
|
||||
}
|
||||
|
||||
export interface ModifyGuildRole {
|
||||
name?: string;
|
||||
color?: number;
|
||||
hoist?: boolean;
|
||||
mentionable?: boolean;
|
||||
unicodeEmoji?: string;
|
||||
}
|
||||
|
||||
export interface CreateGuildEmoji {
|
||||
name: string;
|
||||
image: string;
|
||||
roles?: Snowflake[];
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export interface ModifyGuildEmoji {
|
||||
name?: string;
|
||||
roles?: Snowflake[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://discord.com/developers/docs/resources/guild#create-guild-ban
|
||||
*/
|
||||
export interface CreateGuildBan {
|
||||
deleteMessageDays?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://discord.com/developers/docs/resources/guild#modify-guild-member
|
||||
*/
|
||||
export interface ModifyGuildMember {
|
||||
nick?: string;
|
||||
roles?: Snowflake[];
|
||||
mute?: boolean;
|
||||
deaf?: boolean;
|
||||
channelId?: Snowflake;
|
||||
communicationDisabledUntil?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://discord.com/developers/docs/resources/guild#begin-guild-prune
|
||||
*/
|
||||
export interface BeginGuildPrune {
|
||||
days?: number;
|
||||
computePruneCount?: boolean;
|
||||
includeRoles?: Snowflake[];
|
||||
}
|
||||
|
||||
export interface ModifyRolePositions {
|
||||
id: Snowflake;
|
||||
position?: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a guild
|
||||
* @link https://discord.com/developers/docs/resources/guild#guild-object
|
||||
*/
|
||||
export class Guild extends BaseGuild implements Model {
|
||||
constructor(session: Session, data: DiscordGuild) {
|
||||
super(session, data);
|
||||
|
||||
this.splashHash = data.splash ? iconHashToBigInt(data.splash) : undefined;
|
||||
this.discoverySplashHash = data.discovery_splash ? iconHashToBigInt(data.discovery_splash) : undefined;
|
||||
this.ownerId = data.owner_id;
|
||||
this.widgetEnabled = !!data.widget_enabled;
|
||||
this.widgetChannelId = data.widget_channel_id ? data.widget_channel_id : undefined;
|
||||
this.vefificationLevel = data.verification_level;
|
||||
this.defaultMessageNotificationLevel = data.default_message_notifications;
|
||||
this.explicitContentFilterLevel = data.explicit_content_filter;
|
||||
this.members = data.members?.map((member) => new Member(session, { ...member, user: member.user! }, data.id)) ??
|
||||
[];
|
||||
this.roles = data.roles.map((role) => new Role(session, role, data.id));
|
||||
this.emojis = data.emojis.map((guildEmoji) => new GuildEmoji(session, guildEmoji, data.id));
|
||||
}
|
||||
|
||||
splashHash?: bigint;
|
||||
discoverySplashHash?: bigint;
|
||||
ownerId: Snowflake;
|
||||
widgetEnabled: boolean;
|
||||
widgetChannelId?: Snowflake;
|
||||
vefificationLevel: VerificationLevels;
|
||||
defaultMessageNotificationLevel: DefaultMessageNotificationLevels;
|
||||
explicitContentFilterLevel: ExplicitContentFilterLevels;
|
||||
members: Member[];
|
||||
roles: Role[];
|
||||
emojis: GuildEmoji[];
|
||||
|
||||
/**
|
||||
* 'null' would reset the nickname
|
||||
*/
|
||||
async editBotNickname(options: { nick: string | null; reason?: string }) {
|
||||
const result = await this.session.rest.runMethod<{ nick?: string } | undefined>(
|
||||
this.session.rest,
|
||||
"PATCH",
|
||||
Routes.USER_NICK(this.id),
|
||||
options,
|
||||
);
|
||||
|
||||
return result?.nick;
|
||||
}
|
||||
|
||||
async createEmoji(options: CreateGuildEmoji): Promise<GuildEmoji> {
|
||||
if (options.image && !options.image.startsWith("data:image/")) {
|
||||
options.image = await urlToBase64(options.image);
|
||||
}
|
||||
|
||||
const emoji = await this.session.rest.runMethod<DiscordEmoji>(
|
||||
this.session.rest,
|
||||
"POST",
|
||||
Routes.GUILD_EMOJIS(this.id),
|
||||
options,
|
||||
);
|
||||
|
||||
return new GuildEmoji(this.session, emoji, this.id);
|
||||
}
|
||||
|
||||
async deleteEmoji(id: Snowflake, { reason }: { reason?: string } = {}): Promise<void> {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.GUILD_EMOJI(this.id, id),
|
||||
{ reason },
|
||||
);
|
||||
}
|
||||
|
||||
async editEmoji(id: Snowflake, options: ModifyGuildEmoji): Promise<GuildEmoji> {
|
||||
const emoji = await this.session.rest.runMethod<DiscordEmoji>(
|
||||
this.session.rest,
|
||||
"PATCH",
|
||||
Routes.GUILD_EMOJI(this.id, id),
|
||||
options,
|
||||
);
|
||||
|
||||
return new GuildEmoji(this.session, emoji, this.id);
|
||||
}
|
||||
|
||||
async createRole(options: CreateRole): Promise<Role> {
|
||||
let icon: string | undefined;
|
||||
|
||||
if (options.iconHash) {
|
||||
if (typeof options.iconHash === "string") {
|
||||
icon = options.iconHash;
|
||||
} else {
|
||||
icon = iconBigintToHash(options.iconHash);
|
||||
}
|
||||
}
|
||||
|
||||
const role = await this.session.rest.runMethod<DiscordRole>(
|
||||
this.session.rest,
|
||||
"PUT",
|
||||
Routes.GUILD_ROLES(this.id),
|
||||
{
|
||||
name: options.name,
|
||||
color: options.color,
|
||||
icon,
|
||||
unicode_emoji: options.unicodeEmoji,
|
||||
hoist: options.hoist,
|
||||
mentionable: options.mentionable,
|
||||
},
|
||||
);
|
||||
|
||||
return new Role(this.session, role, this.id);
|
||||
}
|
||||
|
||||
async deleteRole(roleId: Snowflake): Promise<void> {
|
||||
await this.session.rest.runMethod<undefined>(this.session.rest, "DELETE", Routes.GUILD_ROLE(this.id, roleId));
|
||||
}
|
||||
|
||||
async editRole(roleId: Snowflake, options: ModifyGuildRole): Promise<Role> {
|
||||
const role = await this.session.rest.runMethod<DiscordRole>(
|
||||
this.session.rest,
|
||||
"PATCH",
|
||||
Routes.GUILD_ROLE(this.id, roleId),
|
||||
{
|
||||
name: options.name,
|
||||
color: options.color,
|
||||
hoist: options.hoist,
|
||||
mentionable: options.mentionable,
|
||||
},
|
||||
);
|
||||
|
||||
return new Role(this.session, role, this.id);
|
||||
}
|
||||
|
||||
async addRole(memberId: Snowflake, roleId: Snowflake, { reason }: { reason?: string } = {}) {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"PUT",
|
||||
Routes.GUILD_MEMBER_ROLE(this.id, memberId, roleId),
|
||||
{ reason },
|
||||
);
|
||||
}
|
||||
|
||||
async removeRole(memberId: Snowflake, roleId: Snowflake, { reason }: { reason?: string } = {}) {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.GUILD_MEMBER_ROLE(this.id, memberId, roleId),
|
||||
{ reason },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the roles moved
|
||||
*/
|
||||
async moveRoles(options: ModifyRolePositions[]) {
|
||||
const roles = await this.session.rest.runMethod<DiscordRole[]>(
|
||||
this.session.rest,
|
||||
"PATCH",
|
||||
Routes.GUILD_ROLES(this.id),
|
||||
options,
|
||||
);
|
||||
|
||||
return roles.map((role) => new Role(this.session, role, this.id));
|
||||
}
|
||||
|
||||
async deleteInvite(inviteCode: string): Promise<void> {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.INVITE(inviteCode),
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
async fetchInvite(inviteCode: string, options: GetInvite): Promise<Invite> {
|
||||
const inviteMetadata = await this.session.rest.runMethod<DiscordInviteMetadata>(
|
||||
this.session.rest,
|
||||
"GET",
|
||||
Routes.INVITE(inviteCode, options),
|
||||
);
|
||||
|
||||
return new Invite(this.session, inviteMetadata);
|
||||
}
|
||||
|
||||
async fetchInvites(): Promise<Invite[]> {
|
||||
const invites = await this.session.rest.runMethod<DiscordInviteMetadata[]>(
|
||||
this.session.rest,
|
||||
"GET",
|
||||
Routes.GUILD_INVITES(this.id),
|
||||
);
|
||||
|
||||
return invites.map((invite) => new Invite(this.session, invite));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bans the member
|
||||
*/
|
||||
async banMember(memberId: Snowflake, options: CreateGuildBan) {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"PUT",
|
||||
Routes.GUILD_BAN(this.id, memberId),
|
||||
options
|
||||
? {
|
||||
delete_message_days: options.deleteMessageDays,
|
||||
reason: options.reason,
|
||||
}
|
||||
: {},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks the member
|
||||
*/
|
||||
async kickMember(memberId: Snowflake, { reason }: { reason?: string }) {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.GUILD_MEMBER(this.id, memberId),
|
||||
{ reason },
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unbans the member
|
||||
* */
|
||||
async unbanMember(memberId: Snowflake) {
|
||||
await this.session.rest.runMethod<undefined>(
|
||||
this.session.rest,
|
||||
"DELETE",
|
||||
Routes.GUILD_BAN(this.id, memberId),
|
||||
);
|
||||
}
|
||||
|
||||
async editMember(memberId: Snowflake, options: ModifyGuildMember) {
|
||||
const member = await this.session.rest.runMethod<DiscordMemberWithUser>(
|
||||
this.session.rest,
|
||||
"PATCH",
|
||||
Routes.GUILD_MEMBER(this.id, memberId),
|
||||
{
|
||||
nick: options.nick,
|
||||
roles: options.roles,
|
||||
mute: options.mute,
|
||||
deaf: options.deaf,
|
||||
channel_id: options.channelId,
|
||||
communication_disabled_until: options.communicationDisabledUntil
|
||||
? new Date(options.communicationDisabledUntil).toISOString()
|
||||
: undefined,
|
||||
},
|
||||
);
|
||||
|
||||
return new Member(this.session, member, this.id);
|
||||
}
|
||||
|
||||
async pruneMembers(options: BeginGuildPrune): Promise<number> {
|
||||
const result = await this.session.rest.runMethod<{ pruned: number }>(
|
||||
this.session.rest,
|
||||
"POST",
|
||||
Routes.GUILD_PRUNE(this.id),
|
||||
{
|
||||
days: options.days,
|
||||
compute_prune_count: options.computePruneCount,
|
||||
include_roles: options.includeRoles,
|
||||
},
|
||||
);
|
||||
|
||||
return result.pruned;
|
||||
}
|
||||
|
||||
async getPruneCount(): Promise<number> {
|
||||
const result = await this.session.rest.runMethod<{ pruned: number }>(
|
||||
this.session.rest,
|
||||
"GET",
|
||||
Routes.GUILD_PRUNE(this.id),
|
||||
);
|
||||
|
||||
return result.pruned;
|
||||
}
|
||||
}
|
||||
|
||||
export default Guild;
|
19
structures/guilds/InviteGuild.ts
Normal file
19
structures/guilds/InviteGuild.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type { DiscordGuild } from "../../vendor/external.ts";
|
||||
import AnonymousGuild from "./AnonymousGuild.ts";
|
||||
import WelcomeScreen from "../WelcomeScreen.ts";
|
||||
|
||||
export class InviteGuild extends AnonymousGuild implements Model {
|
||||
constructor(session: Session, data: Partial<DiscordGuild>) {
|
||||
super(session, data);
|
||||
|
||||
if (data.welcome_screen) {
|
||||
this.welcomeScreen = new WelcomeScreen(session, data.welcome_screen);
|
||||
}
|
||||
}
|
||||
|
||||
welcomeScreen?: WelcomeScreen;
|
||||
}
|
||||
|
||||
export default InviteGuild;
|
145
structures/interactions/Interaction.ts
Normal file
145
structures/interactions/Interaction.ts
Normal file
@ -0,0 +1,145 @@
|
||||
import type { Model } from "../Base.ts";
|
||||
import type { Snowflake } from "../../util/Snowflake.ts";
|
||||
import type { Session } from "../../session/Session.ts";
|
||||
import type {
|
||||
DiscordInteraction,
|
||||
DiscordMessage,
|
||||
FileContent,
|
||||
InteractionResponseTypes,
|
||||
InteractionTypes,
|
||||
} from "../../vendor/external.ts";
|
||||
import type { MessageFlags } from "../../util/shared/flags.ts";
|
||||
import type { AllowedMentions } from "../Message.ts";
|
||||
import User from "../User.ts";
|
||||
import Message from "../Message.ts";
|
||||
import Member from "../Member.ts";
|
||||
import * as Routes from "../../util/Routes.ts";
|
||||
|
||||
export interface InteractionResponse {
|
||||
type: InteractionResponseTypes;
|
||||
data?: InteractionApplicationCommandCallbackData;
|
||||
}
|
||||
|
||||
export interface InteractionApplicationCommandCallbackData {
|
||||
content?: string;
|
||||
tts?: boolean;
|
||||
allowedMentions?: AllowedMentions;
|
||||
files?: FileContent[];
|
||||
customId?: string;
|
||||
title?: string;
|
||||
// components?: Component[];
|
||||
flags?: MessageFlags;
|
||||
choices?: ApplicationCommandOptionChoice[];
|
||||
}
|
||||
|
||||
/** https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoptionchoice */
|
||||
export interface ApplicationCommandOptionChoice {
|
||||
name: string;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
// TODO: abstract Interaction, CommandInteraction, ComponentInteraction, PingInteraction, etc
|
||||
|
||||
export class Interaction implements Model {
|
||||
constructor(session: Session, data: DiscordInteraction) {
|
||||
this.session = session;
|
||||
this.id = data.id;
|
||||
this.token = data.token;
|
||||
this.type = data.type;
|
||||
this.guildId = data.guild_id;
|
||||
this.channelId = data.channel_id;
|
||||
this.applicationId = data.application_id;
|
||||
this.locale = data.locale;
|
||||
this.data = data.data;
|
||||
|
||||
if (!data.guild_id) {
|
||||
this.user = new User(session, data.user!);
|
||||
} else {
|
||||
this.member = new Member(session, data.member!, data.guild_id);
|
||||
}
|
||||
}
|
||||
|
||||
readonly session: Session;
|
||||
readonly id: Snowflake;
|
||||
readonly token: string;
|
||||
|
||||
type: InteractionTypes;
|
||||
guildId?: Snowflake;
|
||||
channelId?: Snowflake;
|
||||
applicationId?: Snowflake;
|
||||
locale?: string;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
data: any;
|
||||
user?: User;
|
||||
member?: Member;
|
||||
|
||||
async respond({ type, data }: InteractionResponse) {
|
||||
const toSend = {
|
||||
tts: data?.tts,
|
||||
title: data?.title,
|
||||
flags: data?.flags,
|
||||
content: data?.content,
|
||||
choices: data?.choices,
|
||||
custom_id: data?.customId,
|
||||
allowed_mentions: data?.allowedMentions
|
||||
? {
|
||||
users: data.allowedMentions.users,
|
||||
roles: data.allowedMentions.roles,
|
||||
parse: data.allowedMentions.parse,
|
||||
replied_user: data.allowedMentions.repliedUser,
|
||||
}
|
||||
: { parse: [] },
|
||||
};
|
||||
|
||||
if (this.session.unrepliedInteractions.delete(BigInt(this.id))) {
|
||||
await this.session.rest.sendRequest<undefined>(
|
||||
this.session.rest,
|
||||
{
|
||||
url: Routes.INTERACTION_ID_TOKEN(this.id, this.token),
|
||||
method: "POST",
|
||||
payload: this.session.rest.createRequestBody(this.session.rest, {
|
||||
method: "POST",
|
||||
body: {
|
||||
type: type,
|
||||
data: toSend,
|
||||
file: data?.files,
|
||||
},
|
||||
headers: {
|
||||
// remove authorization header
|
||||
Authorization: "",
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.session.rest.sendRequest<DiscordMessage>(
|
||||
this.session.rest,
|
||||
{
|
||||
url: Routes.WEBHOOK(this.session.applicationId ?? this.session.botId, this.token),
|
||||
method: "POST",
|
||||
payload: this.session.rest.createRequestBody(this.session.rest, {
|
||||
method: "POST",
|
||||
body: {
|
||||
...toSend,
|
||||
file: data?.files,
|
||||
},
|
||||
headers: {
|
||||
// remove authorization header
|
||||
Authorization: "",
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
return new Message(this.session, result);
|
||||
}
|
||||
|
||||
inGuild(): this is Interaction & { user: undefined; guildId: Snowflake; member: Member } {
|
||||
return !!this.guildId;
|
||||
}
|
||||
}
|
||||
|
||||
export default Interaction;
|
Loading…
x
Reference in New Issue
Block a user