mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-03 05:26:07 +00:00
refactor: structures & folders
This commit is contained in:
parent
e66356f2c4
commit
d1d0a1ce76
@ -15,14 +15,14 @@ import type {
|
|||||||
} from "../vendor/external.ts";
|
} from "../vendor/external.ts";
|
||||||
import type { Snowflake } from "../util/Snowflake.ts";
|
import type { Snowflake } from "../util/Snowflake.ts";
|
||||||
import type { Session } from "../session/Session.ts";
|
import type { Session } from "../session/Session.ts";
|
||||||
import type { Channel } from "../structures/BaseChannel.ts";
|
import type { Channel } from "../structures/channels/ChannelFactory.ts";
|
||||||
import ChannelFactory from "../structures/ChannelFactory.ts";
|
import ChannelFactory from "../structures/channels/ChannelFactory.ts";
|
||||||
import GuildChannel from "../structures/GuildChannel.ts";
|
import GuildChannel from "../structures/channels/GuildChannel.ts";
|
||||||
import ThreadChannel from "../structures/ThreadChannel.ts";
|
import ThreadChannel from "../structures/channels/ThreadChannel.ts";
|
||||||
import Member from "../structures/Member.ts";
|
import Member from "../structures/Member.ts";
|
||||||
import Message from "../structures/Message.ts";
|
import Message from "../structures/Message.ts";
|
||||||
import User from "../structures/User.ts";
|
import User from "../structures/User.ts";
|
||||||
import Interaction from "../structures/Interaction.ts";
|
import Interaction from "../structures/interactions/Interaction.ts";
|
||||||
|
|
||||||
export type RawHandler<T> = (...args: [Session, number, T]) => void;
|
export type RawHandler<T> = (...args: [Session, number, T]) => void;
|
||||||
export type Handler<T extends unknown[]> = (...args: T) => unknown;
|
export type Handler<T extends unknown[]> = (...args: T) => unknown;
|
||||||
@ -103,8 +103,8 @@ export const THREAD_LIST_SYNC: RawHandler<DiscordThreadListSync> = (session, _sh
|
|||||||
guildId: payload.guild_id,
|
guildId: payload.guild_id,
|
||||||
channelIds: payload.channel_ids ?? [],
|
channelIds: payload.channel_ids ?? [],
|
||||||
threads: payload.threads.map((channel) => new ThreadChannel(session, channel, payload.guild_id)),
|
threads: payload.threads.map((channel) => new ThreadChannel(session, channel, payload.guild_id)),
|
||||||
// @ts-ignore: TODO: thread member structure
|
|
||||||
members: payload.members.map((member) =>
|
members: payload.members.map((member) =>
|
||||||
|
// @ts-ignore: TODO: thread member structure
|
||||||
new Member(session, member as DiscordMemberWithUser, payload.guild_id)
|
new Member(session, member as DiscordMemberWithUser, payload.guild_id)
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
28
mod.ts
28
mod.ts
@ -1,29 +1,26 @@
|
|||||||
export * from "./structures/AnonymousGuild.ts";
|
|
||||||
export * from "./structures/Attachment.ts";
|
export * from "./structures/Attachment.ts";
|
||||||
export * from "./structures/Base.ts";
|
export * from "./structures/Base.ts";
|
||||||
export * from "./structures/BaseGuild.ts";
|
|
||||||
export * from "./structures/BaseChannel.ts";
|
|
||||||
export * from "./structures/DMChannel.ts";
|
|
||||||
export * from "./structures/Embed.ts";
|
export * from "./structures/Embed.ts";
|
||||||
export * from "./structures/Emoji.ts";
|
export * from "./structures/Emoji.ts";
|
||||||
export * from "./structures/Guild.ts";
|
|
||||||
export * from "./structures/GuildChannel.ts";
|
|
||||||
export * from "./structures/GuildEmoji.ts";
|
export * from "./structures/GuildEmoji.ts";
|
||||||
export * from "./structures/Interaction.ts";
|
|
||||||
export * from "./structures/Invite.ts";
|
export * from "./structures/Invite.ts";
|
||||||
export * from "./structures/InviteGuild.ts";
|
|
||||||
export * from "./structures/Member.ts";
|
export * from "./structures/Member.ts";
|
||||||
export * from "./structures/Message.ts";
|
export * from "./structures/Message.ts";
|
||||||
export * from "./structures/NewsChannel.ts";
|
|
||||||
export * from "./structures/Permissions.ts";
|
export * from "./structures/Permissions.ts";
|
||||||
export * from "./structures/Role.ts";
|
export * from "./structures/Role.ts";
|
||||||
export * from "./structures/TextChannel.ts";
|
|
||||||
export * from "./structures/ThreadChannel.ts";
|
|
||||||
export * from "./structures/User.ts";
|
export * from "./structures/User.ts";
|
||||||
export * from "./structures/VoiceChannel.ts";
|
|
||||||
export * from "./structures/WelcomeChannel.ts";
|
export * from "./structures/WelcomeChannel.ts";
|
||||||
export * from "./structures/WelcomeScreen.ts";
|
export * from "./structures/WelcomeScreen.ts";
|
||||||
|
|
||||||
|
export * from "./structures/channels/BaseChannel.ts";
|
||||||
|
export * from "./structures/channels/ChannelFactory.ts";
|
||||||
|
export * from "./structures/channels/DMChannel.ts";
|
||||||
|
export * from "./structures/channels/GuildChannel.ts";
|
||||||
|
export * from "./structures/channels/NewsChannel.ts";
|
||||||
|
export * from "./structures/channels/TextChannel.ts";
|
||||||
|
export * from "./structures/channels/ThreadChannel.ts";
|
||||||
|
export * from "./structures/channels/VoiceChannel.ts";
|
||||||
|
|
||||||
export * from "./structures/components/ActionRowComponent.ts";
|
export * from "./structures/components/ActionRowComponent.ts";
|
||||||
export * from "./structures/components/ButtonComponent.ts";
|
export * from "./structures/components/ButtonComponent.ts";
|
||||||
export * from "./structures/components/Component.ts";
|
export * from "./structures/components/Component.ts";
|
||||||
@ -31,6 +28,13 @@ export * from "./structures/components/LinkButtonComponent.ts";
|
|||||||
export * from "./structures/components/SelectMenuComponent.ts";
|
export * from "./structures/components/SelectMenuComponent.ts";
|
||||||
export * from "./structures/components/TextInputComponent.ts";
|
export * from "./structures/components/TextInputComponent.ts";
|
||||||
|
|
||||||
|
export * from "./structures/guilds/AnonymousGuild.ts";
|
||||||
|
export * from "./structures/guilds/BaseGuild.ts";
|
||||||
|
export * from "./structures/guilds/Guild.ts";
|
||||||
|
export * from "./structures/guilds/InviteGuild.ts";
|
||||||
|
|
||||||
|
export * from "./structures/interactions/Interaction.ts";
|
||||||
|
|
||||||
export * from "./session/Session.ts";
|
export * from "./session/Session.ts";
|
||||||
|
|
||||||
export * from "./util/shared/flags.ts";
|
export * from "./util/shared/flags.ts";
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
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;
|
|
@ -1,51 +0,0 @@
|
|||||||
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;
|
|
@ -1,41 +0,0 @@
|
|||||||
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;
|
|
@ -1,39 +0,0 @@
|
|||||||
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;
|
|
@ -1,40 +0,0 @@
|
|||||||
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 TextChannel, BaseChannel {}
|
|
||||||
|
|
||||||
export default DMChannel;
|
|
@ -1,367 +0,0 @@
|
|||||||
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;
|
|
@ -1,70 +0,0 @@
|
|||||||
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;
|
|
@ -2,8 +2,8 @@ import type { Model } from "./Base.ts";
|
|||||||
import type { Snowflake } from "../util/Snowflake.ts";
|
import type { Snowflake } from "../util/Snowflake.ts";
|
||||||
import type { Session } from "../session/Session.ts";
|
import type { Session } from "../session/Session.ts";
|
||||||
import type { DiscordEmoji } from "../vendor/external.ts";
|
import type { DiscordEmoji } from "../vendor/external.ts";
|
||||||
import type { ModifyGuildEmoji } from "./Guild.ts";
|
import type { ModifyGuildEmoji } from "./guilds/Guild.ts";
|
||||||
import Guild from "./Guild.ts";
|
import Guild from "./guilds/Guild.ts";
|
||||||
import Emoji from "./Emoji.ts";
|
import Emoji from "./Emoji.ts";
|
||||||
import User from "./User.ts";
|
import User from "./User.ts";
|
||||||
import * as Routes from "../util/Routes.ts";
|
import * as Routes from "../util/Routes.ts";
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
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;
|
|
@ -1,9 +1,9 @@
|
|||||||
import type { Session } from "../session/Session.ts";
|
import type { Session } from "../session/Session.ts";
|
||||||
import type { DiscordInvite } from "../vendor/external.ts";
|
import type { DiscordInvite } from "../vendor/external.ts";
|
||||||
import { TargetTypes } from "../vendor/external.ts";
|
import { TargetTypes } from "../vendor/external.ts";
|
||||||
import InviteGuild from "./InviteGuild.ts";
|
import InviteGuild from "./guilds/InviteGuild.ts";
|
||||||
import User from "./User.ts";
|
import User from "./User.ts";
|
||||||
import Guild from "./Guild.ts";
|
import Guild from "./guilds/Guild.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @link https://discord.com/developers/docs/resources/invite#invite-object
|
* @link https://discord.com/developers/docs/resources/invite#invite-object
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
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;
|
|
@ -3,10 +3,10 @@ import type { Snowflake } from "../util/Snowflake.ts";
|
|||||||
import type { Session } from "../session/Session.ts";
|
import type { Session } from "../session/Session.ts";
|
||||||
import type { DiscordMemberWithUser } from "../vendor/external.ts";
|
import type { DiscordMemberWithUser } from "../vendor/external.ts";
|
||||||
import type { ImageFormat, ImageSize } from "../util/shared/images.ts";
|
import type { ImageFormat, ImageSize } from "../util/shared/images.ts";
|
||||||
import type { CreateGuildBan, ModifyGuildMember } from "./Guild.ts";
|
import type { CreateGuildBan, ModifyGuildMember } from "./guilds/Guild.ts";
|
||||||
import { iconBigintToHash, iconHashToBigInt } from "../util/hash.ts";
|
import { iconBigintToHash, iconHashToBigInt } from "../util/hash.ts";
|
||||||
import User from "./User.ts";
|
import User from "./User.ts";
|
||||||
import Guild from "./Guild.ts";
|
import Guild from "./guilds/Guild.ts";
|
||||||
import * as Routes from "../util/Routes.ts";
|
import * as Routes from "../util/Routes.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
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;
|
|
@ -4,7 +4,7 @@ import type { Session } from "../session/Session.ts";
|
|||||||
import { Snowflake } from "../util/Snowflake.ts";
|
import { Snowflake } from "../util/Snowflake.ts";
|
||||||
import { iconHashToBigInt } from "../util/hash.ts";
|
import { iconHashToBigInt } from "../util/hash.ts";
|
||||||
import Permissions from "./Permissions.ts";
|
import Permissions from "./Permissions.ts";
|
||||||
import Guild, { ModifyGuildRole } from "./Guild.ts";
|
import Guild, { ModifyGuildRole } from "./guilds/Guild.ts";
|
||||||
|
|
||||||
export class Role implements Model {
|
export class Role implements Model {
|
||||||
constructor(session: Session, data: DiscordRole, guildId: Snowflake) {
|
constructor(session: Session, data: DiscordRole, guildId: Snowflake) {
|
||||||
|
@ -1,215 +0,0 @@
|
|||||||
// 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;
|
|
@ -1,35 +0,0 @@
|
|||||||
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;
|
|
@ -1,60 +0,0 @@
|
|||||||
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;
|
|
Loading…
x
Reference in New Issue
Block a user