diff --git a/deps.ts b/deps.ts index 6656d75..33f5e5f 100644 --- a/deps.ts +++ b/deps.ts @@ -9,3 +9,4 @@ export type { } from 'https://deno.land/x/redis@v0.14.1/mod.ts' export { walk } from 'https://deno.land/std@0.86.0/fs/walk.ts' export { join } from 'https://deno.land/std@0.86.0/path/mod.ts' +export { Mixin } from 'https://esm.sh/ts-mixer' diff --git a/egg.json b/egg.json index 43e6d96..e6aa717 100644 --- a/egg.json +++ b/egg.json @@ -4,7 +4,7 @@ "entry": "./mod.ts", "description": "An easy to use Discord API Library for Deno.", "homepage": "https://github.com/harmonyland/harmony", - "version": "v1.1.3", + "version": "v1.1.4", "files": [ "./src/**/*", "./deps.ts", diff --git a/mod.ts b/mod.ts index fdd25de..8b22bfa 100644 --- a/mod.ts +++ b/mod.ts @@ -71,7 +71,12 @@ export { } from './src/structures/presence.ts' export { Role } from './src/structures/role.ts' export { Snowflake } from './src/utils/snowflake.ts' -export { TextChannel, GuildTextChannel } from './src/structures/textChannel.ts' +export { TextChannel } from './src/structures/textChannel.ts' +export { + GuildTextBasedChannel, + GuildTextChannel, + checkGuildTextBasedChannel +} from './src/structures/guildTextChannel.ts' export type { AllMessageOptions } from './src/structures/textChannel.ts' export { MessageReaction } from './src/structures/messageReaction.ts' export { User } from './src/structures/user.ts' @@ -103,7 +108,10 @@ export type { GuildTextChannelPayload, GuildVoiceChannelPayload, GroupDMChannelPayload, - MessageOptions + MessageOptions, + OverwriteAsArg, + Overwrite, + OverwriteAsOptions } from './src/types/channel.ts' export type { EmojiPayload } from './src/types/emoji.ts' export { Verification } from './src/types/guild.ts' @@ -113,6 +121,7 @@ export type { GuildBanPayload, GuildFeatures, GuildChannels, + GuildTextBasedChannels, GuildCreateOptions, GuildCreateChannelOptions, GuildCreateRolePayload diff --git a/src/gateway/handlers/index.ts b/src/gateway/handlers/index.ts index 9cc7cd4..9775575 100644 --- a/src/gateway/handlers/index.ts +++ b/src/gateway/handlers/index.ts @@ -31,7 +31,8 @@ import { webhooksUpdate } from './webhooksUpdate.ts' import { messageDeleteBulk } from './messageDeleteBulk.ts' import { userUpdate } from './userUpdate.ts' import { typingStart } from './typingStart.ts' -import { GuildTextChannel, TextChannel } from '../../structures/textChannel.ts' +import { TextChannel } from '../../structures/textChannel.ts' +import { GuildTextBasedChannel } from '../../structures/guildTextChannel.ts' import { Guild } from '../../structures/guild.ts' import { User } from '../../structures/user.ts' import { Emoji } from '../../structures/emoji.ts' @@ -263,7 +264,7 @@ export type ClientEvents = { * @param uncached Set of Messages deleted's IDs which were not cached */ messageDeleteBulk: [ - channel: GuildTextChannel, + channel: GuildTextBasedChannel, messages: Collection, uncached: Set ] @@ -356,7 +357,7 @@ export type ClientEvents = { * @param guild Guild in which Webhooks were updated * @param channel Channel of which Webhooks were updated */ - webhooksUpdate: [guild: Guild, channel: GuildTextChannel] + webhooksUpdate: [guild: Guild, channel: GuildTextBasedChannel] /** * An Interaction was created * @param interaction Created interaction object diff --git a/src/gateway/handlers/interactionCreate.ts b/src/gateway/handlers/interactionCreate.ts index fac882a..4419eb1 100644 --- a/src/gateway/handlers/interactionCreate.ts +++ b/src/gateway/handlers/interactionCreate.ts @@ -1,6 +1,6 @@ import { Member } from '../../structures/member.ts' import { Interaction } from '../../structures/slash.ts' -import { GuildTextChannel } from '../../structures/textChannel.ts' +import { GuildTextBasedChannel } from '../../structures/guildTextChannel.ts' import { InteractionPayload } from '../../types/slash.ts' import { Gateway, GatewayEventHandler } from '../index.ts' @@ -17,8 +17,8 @@ export const interactionCreate: GatewayEventHandler = async ( )) as unknown) as Member const channel = - (await gateway.client.channels.get(d.channel_id)) ?? - (await gateway.client.channels.fetch(d.channel_id)) + (await gateway.client.channels.get(d.channel_id)) ?? + (await gateway.client.channels.fetch(d.channel_id)) const interaction = new Interaction(gateway.client, d, { member, diff --git a/src/gateway/handlers/messageDeleteBulk.ts b/src/gateway/handlers/messageDeleteBulk.ts index 245b6e5..b473081 100644 --- a/src/gateway/handlers/messageDeleteBulk.ts +++ b/src/gateway/handlers/messageDeleteBulk.ts @@ -1,5 +1,5 @@ import { Message } from '../../structures/message.ts' -import { GuildTextChannel } from '../../structures/textChannel.ts' +import { GuildTextBasedChannel } from '../../structures/guildTextChannel.ts' import { MessageDeleteBulkPayload } from '../../types/gateway.ts' import { Collection } from '../../utils/collection.ts' import { Gateway, GatewayEventHandler } from '../index.ts' @@ -8,7 +8,7 @@ export const messageDeleteBulk: GatewayEventHandler = async ( gateway: Gateway, d: MessageDeleteBulkPayload ) => { - let channel = await gateway.client.channels.get( + let channel = await gateway.client.channels.get( d.channel_id ) // Fetch the channel if not cached @@ -16,7 +16,7 @@ export const messageDeleteBulk: GatewayEventHandler = async ( // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion channel = (await gateway.client.channels.fetch( d.channel_id - )) as GuildTextChannel + )) as GuildTextBasedChannel const messages = new Collection() const uncached = new Set() diff --git a/src/gateway/handlers/webhooksUpdate.ts b/src/gateway/handlers/webhooksUpdate.ts index 3b3ae6e..652e54c 100644 --- a/src/gateway/handlers/webhooksUpdate.ts +++ b/src/gateway/handlers/webhooksUpdate.ts @@ -1,7 +1,7 @@ import { Gateway, GatewayEventHandler } from '../index.ts' import { Guild } from '../../structures/guild.ts' import { WebhooksUpdatePayload } from '../../types/gateway.ts' -import { GuildTextChannel } from '../../structures/textChannel.ts' +import { GuildTextBasedChannel } from '../../structures/guildTextChannel.ts' export const webhooksUpdate: GatewayEventHandler = async ( gateway: Gateway, @@ -10,9 +10,9 @@ export const webhooksUpdate: GatewayEventHandler = async ( const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) if (guild === undefined) return - const channel: GuildTextChannel | undefined = (await guild.channels.get( + const channel: GuildTextBasedChannel | undefined = (await guild.channels.get( d.channel_id - )) as GuildTextChannel + )) as GuildTextBasedChannel if (channel === undefined) gateway.client.emit('webhooksUpdateUncached', guild, d.channel_id) else gateway.client.emit('webhooksUpdate', guild, channel) diff --git a/src/managers/guildChannels.ts b/src/managers/guildChannels.ts index 2bc6837..266dcf0 100644 --- a/src/managers/guildChannels.ts +++ b/src/managers/guildChannels.ts @@ -5,7 +5,7 @@ import { CategoryChannel } from '../structures/guildCategoryChannel.ts' import { ChannelTypes, GuildChannelPayload, - Overwrite + OverwritePayload } from '../types/channel.ts' import { GuildChannels, GuildChannelPayloads } from '../types/guild.ts' import { CHANNEL, GUILD_CHANNELS } from '../types/endpoint.ts' @@ -20,7 +20,7 @@ export interface CreateChannelOptions { userLimit?: number rateLimitPerUser?: number position?: number - permissionOverwrites?: Overwrite[] + permissionOverwrites?: OverwritePayload[] parent?: CategoryChannel | string nsfw?: boolean } diff --git a/src/models/commandClient.ts b/src/models/commandClient.ts index 1c78a13..c7590c6 100644 --- a/src/models/commandClient.ts +++ b/src/models/commandClient.ts @@ -1,5 +1,5 @@ import { Message } from '../structures/message.ts' -import { GuildTextChannel } from '../structures/textChannel.ts' +import { GuildTextBasedChannel } from '../structures/guildTextChannel.ts' import { Client, ClientOptions } from './client.ts' import { CategoriesManager, @@ -275,7 +275,7 @@ export class CommandClient extends Client implements CommandClientOptions { if ( command.nsfw === true && (msg.guild === undefined || - ((msg.channel as unknown) as GuildTextChannel).nsfw !== true) + ((msg.channel as unknown) as GuildTextBasedChannel).nsfw !== true) ) return this.emit('commandNSFW', ctx) diff --git a/src/structures/channel.ts b/src/structures/channel.ts index 8e973b3..448665c 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -1,6 +1,22 @@ import { Client } from '../models/client.ts' -import { ChannelPayload, ChannelTypes } from '../types/channel.ts' +import { + ChannelPayload, + ChannelTypes, + ModifyChannelOption, + ModifyChannelPayload, + Overwrite, + OverwritePayload, + OverwriteAsArg, + OverrideType +} from '../types/channel.ts' +import { CHANNEL } from '../types/endpoint.ts' +import { GuildChannelPayloads, GuildChannels } from '../types/guild.ts' +import getChannelByType from '../utils/getChannelByType.ts' +import { Permissions } from '../utils/permissions.ts' import { SnowflakeBase } from './base.ts' +import { Guild } from './guild.ts' +import { Member } from './member.ts' +import { Role } from './role.ts' export class Channel extends SnowflakeBase { type: ChannelTypes @@ -21,3 +37,313 @@ export class Channel extends SnowflakeBase { this.id = data.id ?? this.id } } + +export class GuildChannel extends Channel { + guildID: string + name: string + position: number + permissionOverwrites: OverwritePayload[] + guild: Guild + nsfw: boolean + parentID?: string + + constructor(client: Client, data: GuildChannelPayloads, guild: Guild) { + super(client, data) + this.guildID = data.guild_id + this.name = data.name + this.guild = guild + this.position = data.position + this.permissionOverwrites = data.permission_overwrites + this.nsfw = data.nsfw + this.parentID = data.parent_id + } + + readFromData(data: GuildChannelPayloads): void { + super.readFromData(data) + this.guildID = data.guild_id ?? this.guildID + this.name = data.name ?? this.name + this.position = data.position ?? this.position + this.permissionOverwrites = + data.permission_overwrites ?? this.permissionOverwrites + this.nsfw = data.nsfw ?? this.nsfw + this.parentID = data.parent_id ?? this.parentID + } + + /** Get Permission Overties for a specific Member or Role */ + async overwritesFor(target: Member | Role | string): Promise { + const stringToObject = + typeof target === 'string' + ? (await this.guild.members.get(target)) ?? + (await this.guild.roles.get(target)) + : target + + if (stringToObject === undefined) { + throw new Error('Member or Role not found') + } else { + target = stringToObject + } + + const roles = + target instanceof Member ? await target.roles.array() : undefined + + const overwrites: Overwrite[] = [] + + for (const overwrite of this.permissionOverwrites) { + if ( + overwrite.id === this.guild.id || + roles?.some((e) => e.id === overwrite.id) === true || + overwrite.id === target.id + ) { + const id = + (await this.guild.members.get(overwrite.id)) ?? + (await this.guild.roles.get(overwrite.id)) ?? + overwrite.id + const allow = new Permissions(overwrite.allow) + const deny = new Permissions(overwrite.deny) + + overwrites.push({ + id, + type: overwrite.type, + allow, + deny + }) + } + } + + return overwrites + } + + /** Get Permissions for a Member in this Channel */ + async permissionsFor(target: Member | Role | string): Promise { + const id = typeof target === 'string' ? target : target.id + if (id === this.guild.ownerID) return new Permissions(Permissions.ALL) + + const stringToObject = + typeof target === 'string' + ? (await this.guild.members.get(target)) ?? + (await this.guild.roles.get(target)) + : target + + if (stringToObject === undefined) { + throw new Error('Member or Role not found') + } else { + target = stringToObject + } + + if (target.permissions.has('ADMINISTRATOR') === true) + return new Permissions(Permissions.ALL) + + const overwrites = await this.overwritesFor(target) + const everyoneOW = overwrites.find((e) => e.id === this.guild.id) + const roleOWs = overwrites.filter((e) => e.type === 0) + const memberOWs = overwrites.filter((e) => e.type === 1) + + return target.permissions + .remove(everyoneOW !== undefined ? Number(everyoneOW.deny) : 0) + .add(everyoneOW !== undefined ? Number(everyoneOW.allow) : 0) + .remove(roleOWs.length === 0 ? 0 : roleOWs.map((e) => Number(e.deny))) + .add(roleOWs.length === 0 ? 0 : roleOWs.map((e) => Number(e.allow))) + .remove(memberOWs.length === 0 ? 0 : memberOWs.map((e) => Number(e.deny))) + .add(memberOWs.length === 0 ? 0 : memberOWs.map((e) => Number(e.allow))) + } + + async edit(options?: ModifyChannelOption): Promise { + const body: ModifyChannelPayload = { + name: options?.name, + position: options?.position, + permission_overwrites: options?.permissionOverwrites, + parent_id: options?.parentID, + nsfw: options?.nsfw + } + + const resp = await this.client.rest.patch(CHANNEL(this.id), body) + + return ( + (getChannelByType(this.client, resp, this.guild) as + | GuildChannels + | undefined) ?? new GuildChannel(this.client, resp, this.guild) + ) + } + + /** Edit name of the channel */ + async setName(name: string): Promise { + return await this.edit({ name }) + } + + /** Edit NSFW property of the channel */ + async setNSFW(nsfw: boolean): Promise { + return await this.edit({ nsfw }) + } + + /** Set Permission Overwrites of the Channel */ + async setOverwrites(overwrites: OverwriteAsArg[]): Promise { + const result = overwrites.map( + (overwrite): OverwritePayload => { + const id = + typeof overwrite.id === 'string' ? overwrite.id : overwrite.id.id + const allow = + typeof overwrite.allow === 'string' + ? overwrite.allow + : overwrite.allow?.toJSON() ?? '0' + const deny = + typeof overwrite.deny === 'string' + ? overwrite.deny + : overwrite.deny?.toJSON() ?? '0' + const type = + overwrite.id instanceof Role + ? 0 + : overwrite.id instanceof Member + ? 1 + : overwrite.type + if (type === undefined) { + throw new Error('Overwrite type is undefined.') + } + + return { + id, + type, + allow, + deny + } + } + ) + return await this.edit({ permissionOverwrites: result }) + } + + /** Add a Permission Overwrite */ + async addOverwrite(overwrite: OverwriteAsArg): Promise { + const overwrites = this.permissionOverwrites + const id = typeof overwrite.id === 'string' ? overwrite.id : overwrite.id.id + const allow = + typeof overwrite.allow === 'string' + ? overwrite.allow + : overwrite.allow?.toJSON() ?? '0' + const deny = + typeof overwrite.deny === 'string' + ? overwrite.deny + : overwrite.deny?.toJSON() ?? '0' + const type = + overwrite.id instanceof Role + ? 0 + : overwrite.id instanceof Member + ? 1 + : overwrite.type + if (type === undefined) { + throw new Error('Overwrite type is undefined.') + } + + overwrites.push({ + id, + type, + allow, + deny + }) + + return await this.edit({ permissionOverwrites: overwrites }) + } + + /** Remove a Permission Overwrite */ + async removeOverwrite( + target: Member | Role | string + ): Promise { + target = typeof target === 'string' ? target : target.id + if (this.permissionOverwrites.find((e) => e.id === target) === undefined) + throw new Error('Permission Overwrite not found') + const overwrites = this.permissionOverwrites.filter((e) => e.id !== target) + return await this.edit({ permissionOverwrites: overwrites }) + } + + /** Edit a Permission Overwrite */ + async editOverwrite( + overwrite: OverwriteAsArg, + { + overriteAllow = OverrideType.ADD, + overriteDeny = OverrideType.ADD + }: { + overriteAllow: OverrideType + overriteDeny: OverrideType + } + ): Promise { + const id = typeof overwrite.id === 'string' ? overwrite.id : overwrite.id.id + const index = this.permissionOverwrites.findIndex((e) => e.id === id) + if (index < 0) throw new Error('Permission Overwrite not found') + const overwrites = this.permissionOverwrites + + let allow: string + let deny: string + + if ( + overwrite.allow !== undefined && + overriteAllow !== OverrideType.REPLACE + ) { + switch (overriteAllow) { + case OverrideType.ADD: { + const originalAllow = new Permissions(overwrites[index].allow) + const newAllow = new Permissions(overwrite.allow) + + allow = originalAllow.add([newAllow]).toJSON() + break + } + case OverrideType.REMOVE: { + const originalAllow = new Permissions(overwrites[index].allow) + const newAllow = new Permissions(overwrite.allow) + + allow = originalAllow.remove([newAllow]).toJSON() + break + } + } + } else { + allow = + typeof overwrite.allow === 'string' + ? overwrite.allow + : overwrite.allow?.toJSON() ?? overwrites[index].allow + } + + if (overwrite.deny !== undefined && overriteDeny !== OverrideType.REPLACE) { + switch (overriteDeny) { + case OverrideType.ADD: { + const originalDeny = new Permissions(overwrites[index].deny) + const newDeny = new Permissions(overwrite.deny) + + deny = originalDeny.add([newDeny]).toJSON() + break + } + case OverrideType.REMOVE: { + const originalDeny = new Permissions(overwrites[index].deny) + const newDeny = new Permissions(overwrite.deny) + + deny = originalDeny.remove([newDeny]).toJSON() + break + } + } + } else { + deny = + typeof overwrite.deny === 'string' + ? overwrite.deny + : overwrite.deny?.toJSON() ?? overwrites[index].deny + } + + const type = + overwrite.id instanceof Role + ? 0 + : overwrite.id instanceof Member + ? 1 + : overwrite.type + if (type === undefined) { + throw new Error('Overwrite type is undefined.') + } + + overwrites[index] = { + id, + type, + allow, + deny + } + return await this.edit({ permissionOverwrites: overwrites }) + } + + /** Edit position of the channel */ + async setPosition(position: number): Promise { + return await this.edit({ position }) + } +} diff --git a/src/structures/guildCategoryChannel.ts b/src/structures/guildCategoryChannel.ts index 46e4a30..02a00f0 100644 --- a/src/structures/guildCategoryChannel.ts +++ b/src/structures/guildCategoryChannel.ts @@ -1,42 +1,14 @@ -import { Client } from '../models/client.ts' -import { Channel } from './channel.ts' +import { GuildChannel } from './channel.ts' import { GuildCategoryChannelPayload, ModifyGuildCategoryChannelOption, - ModifyGuildCategoryChannelPayload, - Overwrite + ModifyGuildCategoryChannelPayload } from '../types/channel.ts' -import { Guild } from './guild.ts' import { CHANNEL } from '../types/endpoint.ts' -export class CategoryChannel extends Channel { - guildID: string - name: string - position: number - permissionOverwrites: Overwrite[] - guild: Guild - parentID?: string - - constructor(client: Client, data: GuildCategoryChannelPayload, guild: Guild) { - super(client, data) - this.guildID = data.guild_id - this.name = data.name - this.guild = guild - this.position = data.position - this.permissionOverwrites = data.permission_overwrites - this.parentID = data.parent_id - // TODO: Cache in Gateway Event Code - // cache.set('guildcategorychannel', this.id, this) - } - +export class CategoryChannel extends GuildChannel { readFromData(data: GuildCategoryChannelPayload): void { super.readFromData(data) - this.guildID = data.guild_id ?? this.guildID - this.name = data.name ?? this.name - this.position = data.position ?? this.position - this.permissionOverwrites = - data.permission_overwrites ?? this.permissionOverwrites - this.parentID = data.parent_id ?? this.parentID } async edit( diff --git a/src/structures/guildNewsChannel.ts b/src/structures/guildNewsChannel.ts index e6d312e..e6f8f5e 100644 --- a/src/structures/guildNewsChannel.ts +++ b/src/structures/guildNewsChannel.ts @@ -1,61 +1,3 @@ -import { Client } from '../models/client.ts' -import { - GuildNewsChannelPayload, - ModifyGuildNewsChannelOption, - ModifyGuildNewsChannelPayload, - Overwrite -} from '../types/channel.ts' -import { CHANNEL } from '../types/endpoint.ts' -import { Guild } from './guild.ts' -import { TextChannel } from './textChannel.ts' +import { GuildTextBasedChannel } from './guildTextChannel.ts' -export class NewsChannel extends TextChannel { - guildID: string - guild: Guild - name: string - position: number - permissionOverwrites: Overwrite[] - nsfw: boolean - parentID?: string - topic?: string - - constructor(client: Client, data: GuildNewsChannelPayload, guild: Guild) { - super(client, data) - this.guildID = data.guild_id - this.name = data.name - this.guild = guild - this.position = data.position - this.permissionOverwrites = data.permission_overwrites - this.nsfw = data.nsfw - this.parentID = data.parent_id - this.topic = data.topic - } - - readFromData(data: GuildNewsChannelPayload): void { - super.readFromData(data) - this.guildID = data.guild_id ?? this.guildID - this.name = data.name ?? this.name - this.position = data.position ?? this.position - this.permissionOverwrites = - data.permission_overwrites ?? this.permissionOverwrites - this.nsfw = data.nsfw ?? this.nsfw - this.parentID = data.parent_id ?? this.parentID - this.topic = data.topic ?? this.topic - } - - async edit(options?: ModifyGuildNewsChannelOption): Promise { - const body: ModifyGuildNewsChannelPayload = { - name: options?.name, - position: options?.position, - permission_overwrites: options?.permissionOverwrites, - parent_id: options?.parentID, - type: options?.type, - topic: options?.topic, - nsfw: options?.nsfw - } - - const resp = await this.client.rest.patch(CHANNEL(this.id), body) - - return new NewsChannel(this.client, resp, this.guild) - } -} +export class NewsChannel extends GuildTextBasedChannel {} diff --git a/src/structures/guildTextChannel.ts b/src/structures/guildTextChannel.ts new file mode 100644 index 0000000..76f405d --- /dev/null +++ b/src/structures/guildTextChannel.ts @@ -0,0 +1,168 @@ +import { Mixin } from '../../deps.ts' +import { TextChannel } from './textChannel.ts' +import { GuildChannel } from './channel.ts' +import { Client } from '../models/client.ts' +import { + ChannelTypes, + GuildTextBasedChannelPayload, + GuildTextChannelPayload, + ModifyGuildTextBasedChannelOption, + ModifyGuildTextBasedChannelPayload, + ModifyGuildTextChannelOption, + ModifyGuildTextChannelPayload +} from '../types/channel.ts' +import { Guild } from './guild.ts' +import { CHANNEL } from '../types/endpoint.ts' +import { Message } from './message.ts' +import { CreateInviteOptions } from '../managers/invites.ts' +import { Invite } from './invite.ts' +import { CategoryChannel } from './guildCategoryChannel.ts' + +const GUILD_TEXT_BASED_CHANNEL_TYPES: ChannelTypes[] = [ + ChannelTypes.GUILD_TEXT, + ChannelTypes.GUILD_NEWS +] + +/** Represents a Text Channel but in a Guild */ +export class GuildTextBasedChannel extends Mixin(TextChannel, GuildChannel) { + topic?: string + + get mention(): string { + return `<#${this.id}>` + } + + toString(): string { + return this.mention + } + + constructor( + client: Client, + data: GuildTextBasedChannelPayload, + guild: Guild + ) { + super(client, data, guild) + this.topic = data.topic + } + + readFromData(data: GuildTextBasedChannelPayload): void { + super.readFromData(data) + this.topic = data.topic ?? this.topic + } + + /** Edit the Guild Text Channel */ + async edit( + options?: ModifyGuildTextBasedChannelOption + ): Promise { + const body: ModifyGuildTextBasedChannelPayload = { + name: options?.name, + position: options?.position, + permission_overwrites: options?.permissionOverwrites, + parent_id: options?.parentID, + nsfw: options?.nsfw, + topic: options?.topic + // rate_limit_per_user: options?.slowmode + } + + const resp = await this.client.rest.patch(CHANNEL(this.id), body) + + return new GuildTextBasedChannel(this.client, resp, this.guild) + } + + /** + * Bulk Delete Messages in a Guild Text Channel + * @param messages Messages to delete. Can be a number, or Array of Message or IDs + */ + async bulkDelete( + messages: Array | number + ): Promise { + let ids: string[] = [] + + if (Array.isArray(messages)) + ids = messages.map((e) => (typeof e === 'string' ? e : e.id)) + else { + let list = await this.messages.array() + if (list.length < messages) list = (await this.fetchMessages()).array() + ids = list + .sort((b, a) => a.createdAt.getTime() - b.createdAt.getTime()) + .filter((e, i) => i < messages) + .filter( + (e) => + new Date().getTime() - e.createdAt.getTime() <= + 1000 * 60 * 60 * 24 * 14 + ) + .map((e) => e.id) + } + + ids = [...new Set(ids)] + if (ids.length < 2 || ids.length > 100) + throw new Error('bulkDelete can only delete messages in range 2-100') + + await this.client.rest.api.channels[this.id].messages['bulk-delete'].post({ + messages: ids + }) + + return this + } + + /** Create an Invite for this Channel */ + async createInvite(options?: CreateInviteOptions): Promise { + return this.guild.invites.create(this.id, options) + } + + /** Edit topic of the channel */ + async setTopic(topic: string): Promise { + return await this.edit({ topic }) + } + + /** Edit category of the channel */ + async setCategory( + category: CategoryChannel | string + ): Promise { + return await this.edit({ + parentID: typeof category === 'object' ? category.id : category + }) + } +} + +export const checkGuildTextBasedChannel = ( + channel: TextChannel +): channel is GuildTextBasedChannel => + GUILD_TEXT_BASED_CHANNEL_TYPES.includes(channel.type) + +export class GuildTextChannel extends GuildTextBasedChannel { + slowmode: number + + constructor(client: Client, data: GuildTextChannelPayload, guild: Guild) { + super(client, data, guild) + this.slowmode = data.rate_limit_per_user + } + + readFromData(data: GuildTextChannelPayload): void { + super.readFromData(data) + this.slowmode = data.rate_limit_per_user ?? this.slowmode + } + + /** Edit the Guild Text Channel */ + async edit( + options?: ModifyGuildTextChannelOption + ): Promise { + const body: ModifyGuildTextChannelPayload = { + name: options?.name, + position: options?.position, + permission_overwrites: options?.permissionOverwrites, + parent_id: options?.parentID, + nsfw: options?.nsfw, + topic: options?.topic, + rate_limit_per_user: options?.slowmode + } + + const resp = await this.client.rest.patch(CHANNEL(this.id), body) + + return new GuildTextChannel(this.client, resp, this.guild) + } + + /** Edit Slowmode of the channel */ + async setSlowmode(slowmode?: number | null): Promise { + return await this.edit({ slowmode: slowmode ?? null }) + } +} diff --git a/src/structures/guildVoiceChannel.ts b/src/structures/guildVoiceChannel.ts index 0e452dc..d1dc287 100644 --- a/src/structures/guildVoiceChannel.ts +++ b/src/structures/guildVoiceChannel.ts @@ -4,11 +4,10 @@ import { Client } from '../models/client.ts' import { GuildVoiceChannelPayload, ModifyVoiceChannelOption, - ModifyVoiceChannelPayload, - Overwrite + ModifyVoiceChannelPayload } from '../types/channel.ts' import { CHANNEL } from '../types/endpoint.ts' -import { Channel } from './channel.ts' +import { GuildChannel } from './channel.ts' import { Guild } from './guild.ts' import { VoiceState } from './voiceState.ts' @@ -16,26 +15,14 @@ export interface VoiceServerData extends VoiceServerUpdateData { sessionID: string } -export class VoiceChannel extends Channel { +export class VoiceChannel extends GuildChannel { bitrate: string userLimit: number - guildID: string - name: string - guild: Guild - position: number - permissionOverwrites: Overwrite[] - parentID?: string constructor(client: Client, data: GuildVoiceChannelPayload, guild: Guild) { - super(client, data) + super(client, data, guild) this.bitrate = data.bitrate this.userLimit = data.user_limit - this.guildID = data.guild_id - this.name = data.name - this.position = data.position - this.guild = guild - this.permissionOverwrites = data.permission_overwrites - this.parentID = data.parent_id } /** Join the Voice Channel */ @@ -104,12 +91,6 @@ export class VoiceChannel extends Channel { super.readFromData(data) this.bitrate = data.bitrate ?? this.bitrate this.userLimit = data.user_limit ?? this.userLimit - this.guildID = data.guild_id ?? this.guildID - this.name = data.name ?? this.name - this.position = data.position ?? this.position - this.permissionOverwrites = - data.permission_overwrites ?? this.permissionOverwrites - this.parentID = data.parent_id ?? this.parentID } async edit(options?: ModifyVoiceChannelOption): Promise { diff --git a/src/structures/message.ts b/src/structures/message.ts index 2b387c8..8a9a360 100644 --- a/src/structures/message.ts +++ b/src/structures/message.ts @@ -13,7 +13,8 @@ import { Member } from './member.ts' import { Embed } from './embed.ts' import { CHANNEL_MESSAGE } from '../types/endpoint.ts' import { MessageMentions } from './messageMentions.ts' -import { GuildTextChannel, TextChannel } from './textChannel.ts' +import { TextChannel } from './textChannel.ts' +import { GuildTextBasedChannel } from './guildTextChannel.ts' import { Guild } from './guild.ts' import { MessageReactionsManager } from '../managers/messageReactions.ts' import { MessageSticker } from './messageSticker.ts' @@ -126,8 +127,10 @@ export class Message extends SnowflakeBase { const newMember = await this.guild?.members.get(this.member?.id) if (newMember !== undefined) this.member = newMember } - if (((this.channel as unknown) as GuildTextChannel).guild !== undefined) - this.guild = ((this.channel as unknown) as GuildTextChannel).guild + if ( + ((this.channel as unknown) as GuildTextBasedChannel).guild !== undefined + ) + this.guild = ((this.channel as unknown) as GuildTextBasedChannel).guild if (this.guild !== undefined && this.guildID === undefined) this.guildID = this.guild.id } diff --git a/src/structures/messageMentions.ts b/src/structures/messageMentions.ts index 50e3c16..4d406d8 100644 --- a/src/structures/messageMentions.ts +++ b/src/structures/messageMentions.ts @@ -1,7 +1,7 @@ import { Client } from '../models/client.ts' import { MessagePayload } from '../types/channel.ts' import { Collection } from '../utils/collection.ts' -import { GuildTextChannel } from './textChannel.ts' +import { GuildTextBasedChannel } from './guildTextChannel.ts' import { Message } from './message.ts' import { Role } from './role.ts' import { User } from './user.ts' @@ -11,7 +11,7 @@ export class MessageMentions { message: Message users: Collection = new Collection() roles: Collection = new Collection() - channels: Collection = new Collection() + channels: Collection = new Collection() everyone: boolean = false static EVERYONE_MENTION = /@(everyone|here)/g @@ -39,7 +39,7 @@ export class MessageMentions { } if (payload.mention_channels !== undefined) { for (const mentionChannel of payload.mention_channels) { - const channel = await this.client.channels.get( + const channel = await this.client.channels.get( mentionChannel.id ) if (channel !== undefined) this.channels.set(channel.id, channel) @@ -51,7 +51,7 @@ export class MessageMentions { if (matchChannels !== null) { for (const id of matchChannels) { const parsedID = id.substr(2, id.length - 3) - const channel = await this.client.channels.get( + const channel = await this.client.channels.get( parsedID ) if (channel !== undefined) this.channels.set(channel.id, channel) diff --git a/src/structures/slash.ts b/src/structures/slash.ts index 388aa56..ff235e9 100644 --- a/src/structures/slash.ts +++ b/src/structures/slash.ts @@ -13,7 +13,8 @@ import { Embed } from './embed.ts' import { Guild } from './guild.ts' import { Member } from './member.ts' import { Message } from './message.ts' -import { GuildTextChannel, TextChannel } from './textChannel.ts' +import { TextChannel } from './textChannel.ts' +import { GuildTextBasedChannel } from './guildTextChannel.ts' import { User } from './user.ts' import { Webhook } from './webhook.ts' @@ -46,7 +47,7 @@ export class Interaction extends SnowflakeBase { token: string id: string data: InteractionData - channel: GuildTextChannel + channel: GuildTextBasedChannel guild: Guild member: Member _savedHook?: Webhook @@ -55,7 +56,7 @@ export class Interaction extends SnowflakeBase { client: Client, data: InteractionPayload, others: { - channel: GuildTextChannel + channel: GuildTextBasedChannel guild: Guild member: Member } diff --git a/src/structures/textChannel.ts b/src/structures/textChannel.ts index 0520520..f978b0c 100644 --- a/src/structures/textChannel.ts +++ b/src/structures/textChannel.ts @@ -1,28 +1,18 @@ -import { CreateInviteOptions } from '../managers/invites.ts' import { MessagesManager } from '../managers/messages.ts' import { Client } from '../models/client.ts' import { - GuildTextChannelPayload, MessageOptions, MessagePayload, - ModifyGuildTextChannelOption, - ModifyGuildTextChannelPayload, - Overwrite, TextChannelPayload } from '../types/channel.ts' import { - CHANNEL, MESSAGE_REACTION_ME, MESSAGE_REACTION_USER } from '../types/endpoint.ts' import { Collection } from '../utils/collection.ts' -import { Permissions } from '../utils/permissions.ts' import { Channel } from './channel.ts' import { Embed } from './embed.ts' import { Emoji } from './emoji.ts' -import { Guild } from './guild.ts' -import { CategoryChannel } from './guildCategoryChannel.ts' -import { Invite } from './invite.ts' import { Member } from './member.ts' import { Message } from './message.ts' import { User } from './user.ts' @@ -185,225 +175,3 @@ export class TextChannel extends Channel { return this } } - -/** Represents a Text Channel but in a Guild */ -export class GuildTextChannel extends TextChannel { - guildID: string - name: string - position: number - permissionOverwrites: Overwrite[] - nsfw: boolean - parentID?: string - slowmode: number - topic?: string - guild: Guild - - get mention(): string { - return `<#${this.id}>` - } - - toString(): string { - return this.mention - } - - constructor(client: Client, data: GuildTextChannelPayload, guild: Guild) { - super(client, data) - this.guildID = data.guild_id - this.name = data.name - this.guild = guild - this.position = data.position - this.permissionOverwrites = data.permission_overwrites - this.nsfw = data.nsfw - this.parentID = data.parent_id - this.topic = data.topic - this.slowmode = data.rate_limit_per_user - } - - readFromData(data: GuildTextChannelPayload): void { - super.readFromData(data) - this.guildID = data.guild_id ?? this.guildID - this.name = data.name ?? this.name - this.position = data.position ?? this.position - this.permissionOverwrites = - data.permission_overwrites ?? this.permissionOverwrites - this.nsfw = data.nsfw ?? this.nsfw - this.parentID = data.parent_id ?? this.parentID - this.topic = data.topic ?? this.topic - this.slowmode = data.rate_limit_per_user ?? this.slowmode - } - - /** Edit the Guild Text Channel */ - async edit( - options?: ModifyGuildTextChannelOption - ): Promise { - const body: ModifyGuildTextChannelPayload = { - name: options?.name, - position: options?.position, - permission_overwrites: options?.permissionOverwrites, - parent_id: options?.parentID, - nsfw: options?.nsfw, - topic: options?.topic, - rate_limit_per_user: options?.slowmode - } - - const resp = await this.client.rest.patch(CHANNEL(this.id), body) - - return new GuildTextChannel(this.client, resp, this.guild) - } - - /** - * Bulk Delete Messages in a Guild Text Channel - * @param messages Messages to delete. Can be a number, or Array of Message or IDs - */ - async bulkDelete( - messages: Array | number - ): Promise { - let ids: string[] = [] - - if (Array.isArray(messages)) - ids = messages.map((e) => (typeof e === 'string' ? e : e.id)) - else { - let list = await this.messages.array() - if (list.length < messages) list = (await this.fetchMessages()).array() - ids = list - .sort((b, a) => a.createdAt.getTime() - b.createdAt.getTime()) - .filter((e, i) => i < messages) - .filter( - (e) => - new Date().getTime() - e.createdAt.getTime() <= - 1000 * 60 * 60 * 24 * 14 - ) - .map((e) => e.id) - } - - ids = [...new Set(ids)] - if (ids.length < 2 || ids.length > 100) - throw new Error('bulkDelete can only delete messages in range 2-100') - - await this.client.rest.api.channels[this.id].messages['bulk-delete'].post({ - messages: ids - }) - - return this - } - - /** Create an Invite for this Channel */ - async createInvite(options?: CreateInviteOptions): Promise { - return this.guild.invites.create(this.id, options) - } - - /** Get Permission Overties for a specific Member */ - async overwritesFor(member: Member | string): Promise { - member = (typeof member === 'string' - ? await this.guild.members.get(member) - : member) as Member - if (member === undefined) throw new Error('Member not found') - const roles = await member.roles.array() - - const overwrites: Overwrite[] = [] - - for (const overwrite of this.permissionOverwrites) { - if (overwrite.id === this.guild.id) { - overwrites.push(overwrite) - } else if (roles.some((e) => e.id === overwrite.id) === true) { - overwrites.push(overwrite) - } else if (overwrite.id === member.id) { - overwrites.push(overwrite) - } - } - - return overwrites - } - - /** Get Permissions for a Member in this Channel */ - async permissionsFor(member: Member | string): Promise { - const id = typeof member === 'string' ? member : member.id - if (id === this.guild.ownerID) return new Permissions(Permissions.ALL) - - member = (typeof member === 'string' - ? await this.guild.members.get(member) - : member) as Member - if (member === undefined) throw new Error('Member not found') - - if (member.permissions.has('ADMINISTRATOR') === true) - return new Permissions(Permissions.ALL) - - const overwrites = await this.overwritesFor(member) - const everyoneOW = overwrites.find((e) => e.id === this.guild.id) - const roleOWs = overwrites.filter((e) => e.type === 0) - const memberOWs = overwrites.filter((e) => e.type === 1) - - return member.permissions - .remove(everyoneOW !== undefined ? Number(everyoneOW.deny) : 0) - .add(everyoneOW !== undefined ? Number(everyoneOW.allow) : 0) - .remove(roleOWs.length === 0 ? 0 : roleOWs.map((e) => Number(e.deny))) - .add(roleOWs.length === 0 ? 0 : roleOWs.map((e) => Number(e.allow))) - .remove(memberOWs.length === 0 ? 0 : memberOWs.map((e) => Number(e.deny))) - .add(memberOWs.length === 0 ? 0 : memberOWs.map((e) => Number(e.allow))) - } - - /** Edit name of the channel */ - async setName(name: string): Promise { - return await this.edit({ name }) - } - - /** Edit topic of the channel */ - async setTopic(topic: string): Promise { - return await this.edit({ topic }) - } - - /** Edit topic of the channel */ - async setCategory( - category: CategoryChannel | string - ): Promise { - return await this.edit({ - parentID: typeof category === 'object' ? category.id : category - }) - } - - /** Edit position of the channel */ - async setPosition(position: number): Promise { - return await this.edit({ position }) - } - - /** Edit Slowmode of the channel */ - async setSlowmode(slowmode?: number | null): Promise { - return await this.edit({ slowmode: slowmode ?? null }) - } - - /** Edit NSFW property of the channel */ - async setNSFW(nsfw: boolean): Promise { - return await this.edit({ nsfw }) - } - - /** Set Permission Overwrites of the Channel */ - async setOverwrites(overwrites: Overwrite[]): Promise { - return await this.edit({ permissionOverwrites: overwrites }) - } - - /** Add a Permission Overwrite */ - async addOverwrite(overwrite: Overwrite): Promise { - const overwrites = this.permissionOverwrites - overwrites.push(overwrite) - return await this.edit({ permissionOverwrites: overwrites }) - } - - /** Remove a Permission Overwrite */ - async removeOverwrite(id: string): Promise { - if (this.permissionOverwrites.findIndex((e) => e.id === id) < 0) - throw new Error('Permission Overwrite not found') - const overwrites = this.permissionOverwrites.filter((e) => e.id !== id) - return await this.edit({ permissionOverwrites: overwrites }) - } - - /** Edit a Permission Overwrite */ - async editOverwrite(overwrite: Overwrite): Promise { - const index = this.permissionOverwrites.findIndex( - (e) => e.id === overwrite.id - ) - if (index < 0) throw new Error('Permission Overwrite not found') - const overwrites = this.permissionOverwrites - overwrites[index] = overwrite - return await this.edit({ permissionOverwrites: overwrites }) - } -} diff --git a/src/test/index.ts b/src/test/index.ts index 0143763..2842fb8 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -9,11 +9,12 @@ import { Guild, EveryChannelTypes, ChannelTypes, - GuildTextChannel + GuildTextChannel, + checkGuildTextBasedChannel, + Permissions } from '../../mod.ts' import { Collector } from '../models/collectors.ts' import { MessageAttachment } from '../structures/message.ts' -import { Permissions } from '../utils/permissions.ts' import { TOKEN } from './config.ts' const client = new Client({ @@ -190,7 +191,8 @@ client.on('messageCreate', async (msg: Message) => { if (typeof vs !== 'object') return vs.channel?.join() } else if (msg.content === '!getOverwrites') { - if (msg.channel.type !== ChannelTypes.GUILD_TEXT) { + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if (!checkGuildTextBasedChannel(msg.channel)) { return msg.channel.send("This isn't a guild text channel!") } // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion @@ -202,16 +204,15 @@ client.on('messageCreate', async (msg: Message) => { `Your permission overwrites:\n${overwrites .map( (over) => - `ID: ${over.id}\nAllowed:\n${new Permissions(over.allow) + `ID: ${over.id}\nAllowed:\n${over.allow .toArray() - .join('\n')}\nDenied:\n${new Permissions(over.deny) - .toArray() - .join('\n')}` + .join('\n')}\nDenied:\n${over.deny.toArray().join('\n')}` ) .join('\n\n')}` ) } else if (msg.content === '!getPermissions') { - if (msg.channel.type !== ChannelTypes.GUILD_TEXT) { + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if (!checkGuildTextBasedChannel(msg.channel)) { return msg.channel.send("This isn't a guild text channel!") } // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion @@ -220,6 +221,18 @@ client.on('messageCreate', async (msg: Message) => { msg.member as Member ) msg.channel.send(`Your permissions:\n${permissions.toArray().join('\n')}`) + } else if (msg.content === '!addBasicOverwrites') { + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if (!checkGuildTextBasedChannel(msg.channel)) { + return msg.channel.send("This isn't a guild text channel!") + } + if (msg.member !== undefined) { + await msg.channel.addOverwrite({ + id: msg.member, + allow: Permissions.DEFAULT.toString() + }) + msg.channel.send(`Done!`) + } } else if (msg.content === '!addAllRoles') { const roles = await msg.guild?.roles.array() if (roles !== undefined) { diff --git a/src/types/channel.ts b/src/types/channel.ts index 7d06156..80bf065 100644 --- a/src/types/channel.ts +++ b/src/types/channel.ts @@ -1,5 +1,8 @@ import { Embed } from '../structures/embed.ts' -import type { Message, MessageAttachment } from '../structures/message.ts' +import { Member } from '../structures/member.ts' +import { Message, MessageAttachment } from '../structures/message.ts' +import { Role } from '../structures/role.ts' +import { Permissions } from '../utils/permissions.ts' import { EmojiPayload } from './emoji.ts' import { MemberPayload } from './guild.ts' import { UserPayload } from './user.ts' @@ -18,25 +21,23 @@ export interface GuildChannelPayload extends ChannelPayload { guild_id: string name: string position: number - permission_overwrites: Overwrite[] + permission_overwrites: OverwritePayload[] + nsfw: boolean parent_id?: string } -export interface GuildTextChannelPayload +export interface GuildTextBasedChannelPayload extends TextChannelPayload, GuildChannelPayload { - nsfw: boolean - rate_limit_per_user: number topic?: string } -export interface GuildNewsChannelPayload - extends TextChannelPayload, - GuildChannelPayload { - topic?: string - nsfw: boolean +export interface GuildTextChannelPayload extends GuildTextBasedChannelPayload { + rate_limit_per_user: number } +export interface GuildNewsChannelPayload extends GuildTextBasedChannelPayload {} + export interface GuildVoiceChannelPayload extends GuildChannelPayload { bitrate: string user_limit: number @@ -59,25 +60,27 @@ export interface GuildCategoryChannelPayload export interface ModifyChannelPayload { name?: string position?: number | null - permission_overwrites?: Overwrite[] | null + permission_overwrites?: OverwritePayload[] | null parent_id?: string + nsfw?: boolean | null } export interface ModifyGuildCategoryChannelPayload extends ModifyChannelPayload {} -export interface ModifyGuildTextChannelPayload extends ModifyChannelPayload { +export interface ModifyGuildTextBasedChannelPayload + extends ModifyChannelPayload { type?: number topic?: string | null - nsfw?: boolean | null +} + +export interface ModifyGuildTextChannelPayload + extends ModifyGuildTextBasedChannelPayload { rate_limit_per_user?: number | null } -export interface ModifyGuildNewsChannelPayload extends ModifyChannelPayload { - type?: number - topic?: string | null - nsfw?: boolean | null -} +export interface ModifyGuildNewsChannelPayload + extends ModifyGuildTextBasedChannelPayload {} export interface ModifyVoiceChannelPayload extends ModifyChannelPayload { bitrate?: number | null @@ -87,37 +90,65 @@ export interface ModifyVoiceChannelPayload extends ModifyChannelPayload { export interface ModifyChannelOption { name?: string position?: number | null - permissionOverwrites?: Overwrite[] | null + permissionOverwrites?: OverwritePayload[] | null parentID?: string + nsfw?: boolean | null } export interface ModifyGuildCategoryChannelOption extends ModifyChannelOption {} -export interface ModifyGuildTextChannelOption extends ModifyChannelOption { +export interface ModifyGuildTextBasedChannelOption extends ModifyChannelOption { type?: number topic?: string | null - nsfw?: boolean | null +} + +export interface ModifyGuildTextChannelOption + extends ModifyGuildTextBasedChannelOption { slowmode?: number | null } -export interface ModifyGuildNewsChannelOption extends ModifyChannelOption { - type?: number - topic?: string | null - nsfw?: boolean | null -} +export interface ModifyGuildNewsChannelOption + extends ModifyGuildTextBasedChannelOption {} export interface ModifyVoiceChannelOption extends ModifyChannelOption { bitrate?: number | null userLimit?: number | null } -export interface Overwrite { +export enum OverwriteType { + ROLE = 0, + USER = 1 +} + +export interface OverwritePayload { id: string - type: number + type: OverwriteType allow: string deny: string } +export interface Overwrite { + id: string | Role | Member + type: OverwriteType + allow: Permissions + deny: Permissions +} + +export interface OverwriteAsOptions { + id: string | Role | Member + type?: OverwriteType + allow?: string | Permissions + deny?: string | Permissions +} + +export type OverwriteAsArg = OverwriteAsOptions | OverwritePayload + +export enum OverrideType { + ADD = 0, + REMOVE = 1, + REPLACE = 2 +} + export enum ChannelTypes { GUILD_TEXT = 0, DM = 1, diff --git a/src/types/guild.ts b/src/types/guild.ts index 30d009a..43758b6 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -1,13 +1,20 @@ +import { GuildChannel } from '../structures/channel.ts' import { Emoji } from '../structures/emoji.ts' import { CategoryChannel } from '../structures/guildCategoryChannel.ts' +import { NewsChannel } from '../structures/guildNewsChannel.ts' import { VoiceChannel } from '../structures/guildVoiceChannel.ts' import { Role } from '../structures/role.ts' -import { GuildTextChannel } from '../structures/textChannel.ts' +import { + GuildTextChannel, + GuildTextBasedChannel +} from '../structures/guildTextChannel.ts' import { ApplicationPayload } from './application.ts' import { ChannelPayload, ChannelTypes, GuildCategoryChannelPayload, + GuildNewsChannelPayload, + GuildTextBasedChannelPayload, GuildTextChannelPayload, GuildVoiceChannelPayload } from './channel.ts' @@ -171,11 +178,26 @@ export interface GuildWidgetPayload { presence_count: number } -export type GuildChannelPayloads = +export type GuildTextBasedPayloads = + | GuildTextBasedChannelPayload | GuildTextChannelPayload + | GuildNewsChannelPayload + +export type GuildChannelPayloads = + | GuildTextBasedPayloads | GuildVoiceChannelPayload | GuildCategoryChannelPayload -export type GuildChannels = GuildTextChannel | VoiceChannel | CategoryChannel + +export type GuildTextBasedChannels = + | GuildTextBasedChannel + | GuildTextChannel + | NewsChannel + +export type GuildChannels = + | GuildChannel + | GuildTextBasedChannels + | VoiceChannel + | CategoryChannel export interface GuildCreatePayload { name: string diff --git a/src/utils/getChannelByType.ts b/src/utils/getChannelByType.ts index 0e5ac9c..04b06bf 100644 --- a/src/utils/getChannelByType.ts +++ b/src/utils/getChannelByType.ts @@ -6,6 +6,7 @@ import { GroupDMChannelPayload, GuildCategoryChannelPayload, GuildNewsChannelPayload, + GuildTextBasedChannelPayload, GuildTextChannelPayload, GuildVoiceChannelPayload, TextChannelPayload @@ -13,16 +14,21 @@ import { import { DMChannel } from '../structures/dmChannel.ts' import { GroupDMChannel } from '../structures/groupChannel.ts' import { CategoryChannel } from '../structures/guildCategoryChannel.ts' +import { + GuildTextBasedChannel, + GuildTextChannel +} from '../structures/guildTextChannel.ts' import { NewsChannel } from '../structures/guildNewsChannel.ts' import { VoiceChannel } from '../structures/guildVoiceChannel.ts' import { Guild } from '../structures/guild.ts' -import { GuildTextChannel, TextChannel } from '../structures/textChannel.ts' -import { Channel } from '../structures/channel.ts' +import { TextChannel } from '../structures/textChannel.ts' +import { Channel, GuildChannel } from '../structures/channel.ts' export type EveryTextChannelTypes = | TextChannel | NewsChannel | GuildTextChannel + | GuildTextBasedChannel | DMChannel | GroupDMChannel @@ -30,11 +36,13 @@ export type EveryTextChannelPayloadTypes = | TextChannelPayload | GuildNewsChannelPayload | GuildTextChannelPayload + | GuildTextBasedChannelPayload | DMChannelPayload | GroupDMChannelPayload export type EveryChannelTypes = | Channel + | GuildChannel | CategoryChannel | VoiceChannel | EveryTextChannelTypes