mirror of
https://github.com/discordeno/discordeno.git
synced 2026-05-31 07:50:07 +00:00
Fix: more client eris mismatches (#2807)
* fix: type errors in nayu * fix: optional file arg in createmessage * fix: add ClientEvents hack * fix: add DiscordRESTError * fix: fmt * fix: fmt * fix: shard prop on guild * fix: permission.has type
This commit is contained in:
@@ -27,7 +27,8 @@ import { delay, getBotIdFromToken, iconBigintToHash, iconHashToBigInt } from '@d
|
||||
import EventEmitter from 'node:events'
|
||||
import Base from './Base.js'
|
||||
import Collection from './Collection.js'
|
||||
import { Intents, IntentStrings } from './Constants.js'
|
||||
import type { IntentStrings } from './Constants.js';
|
||||
import { Intents } from './Constants.js'
|
||||
import {
|
||||
CHANNEL,
|
||||
CHANNEL_BULK_DELETE,
|
||||
@@ -2381,7 +2382,7 @@ export interface ClientOptions {
|
||||
/** How many times to attempt resuming. */
|
||||
maxResumeAttempts?: number
|
||||
/** The intents to use when connection to gateway. */
|
||||
intents?: GatewayIntents | number | (IntentStrings | number)[]
|
||||
intents?: GatewayIntents | number | Array<IntentStrings | number>
|
||||
/** Whether or not to automatically reconnect to gateway. */
|
||||
autoreconnect?: boolean
|
||||
/**
|
||||
|
||||
@@ -557,4 +557,5 @@ export const WebhookTypes = {
|
||||
APPLICATION: 3
|
||||
};
|
||||
|
||||
export type IntentStrings = keyof typeof Intents;
|
||||
export type IntentStrings = keyof typeof Intents;
|
||||
export type PermissionClientStrings = keyof typeof Permissions;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { BitwisePermissionFlags } from '@discordeno/types'
|
||||
import { Base } from '../Base.js'
|
||||
import type { BigString } from '../Client.js'
|
||||
import { PermissionClientStrings, Permissions } from '../Constants.js'
|
||||
|
||||
export class Permission {
|
||||
allow: bigint
|
||||
@@ -36,13 +37,13 @@ export class Permission {
|
||||
}
|
||||
|
||||
/** Check if this permission allows a specific permission */
|
||||
has(permission: bigint | keyof typeof BitwisePermissionFlags): boolean {
|
||||
has(permission: bigint | PermissionClientStrings): boolean {
|
||||
if (this.isAdmin) return true
|
||||
|
||||
if (typeof permission === 'bigint') {
|
||||
return (this.allow & permission) === permission
|
||||
}
|
||||
return !!(this.allow & BigInt(BitwisePermissionFlags[permission]))
|
||||
return !!(this.allow & Permissions[permission])
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
||||
@@ -36,7 +36,7 @@ export class PrivateChannel extends Channel {
|
||||
}
|
||||
|
||||
/** Create a message in a text channel */
|
||||
async createMessage(content: MessageContent, file: FileContent | FileContent[]): Promise<Message> {
|
||||
async createMessage(content: MessageContent, file?: FileContent | FileContent[]): Promise<Message> {
|
||||
return await this.client.createMessage.call(this.client, this.id, content, file)
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ export class TextChannel extends GuildChannel {
|
||||
* @arg {String} file.name What to name the file
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async createMessage(content: MessageContent, file: FileContent | FileContent[]) {
|
||||
async createMessage(content: MessageContent, file?: FileContent | FileContent[]) {
|
||||
return this.client.createMessage.call(this.client, this.id, content, file)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import type Client from '../../Client.js'
|
||||
import type { ImageFormat, ImageSize } from '../../Client.js'
|
||||
import Collection from '../../Collection.js'
|
||||
import { BANNER, GUILD_DISCOVERY_SPLASH, GUILD_ICON, GUILD_SPLASH } from '../../Endpoints.js'
|
||||
import type Shard from '../../gateway/Shard.js'
|
||||
import type {
|
||||
AnyGuildChannel,
|
||||
AnyThreadChannel,
|
||||
@@ -185,10 +186,14 @@ export class Guild extends Base {
|
||||
voiceStates = new Collection<BigString, VoiceState>()
|
||||
/** The cached stage instances in this guild. */
|
||||
stageInstances = new Collection<BigString, StageInstance>()
|
||||
/** The shard that manages this guild. */
|
||||
shard: Shard;
|
||||
|
||||
constructor(data: DiscordGuild, client: Client) {
|
||||
super(data.id)
|
||||
this.client = client
|
||||
this.shard = client.shards.get(client.guildShardMap[this.id] || (Base.getDiscordEpoch(data.id) % (client.options.maxShards as number)) || 0)!;
|
||||
|
||||
this.ownerID = data.owner_id
|
||||
|
||||
this.unavailable = !!data.unavailable
|
||||
|
||||
@@ -47,3 +47,5 @@ export * from './Structures/users/User.js'
|
||||
export * from './typings.js'
|
||||
export * from './utils/BrowserWebSocket.js'
|
||||
export * from './utils/Bucket.js'
|
||||
export * from './utils/DiscordRESTError.js'
|
||||
export * from './utils/generate.js'
|
||||
|
||||
@@ -37,6 +37,16 @@ import type GuildAuditLogEntry from './Structures/guilds/AuditLogEntry.js'
|
||||
import type GuildIntegration from './Structures/guilds/Integration.js'
|
||||
import type Member from './Structures/guilds/Member.js'
|
||||
import type User from './Structures/users/User.js'
|
||||
import type { Guild, Invite } from './index.js'
|
||||
import type Role from './Structures/guilds/Role.js'
|
||||
import type StageInstance from './Structures/guilds/StageInstance.js'
|
||||
import type UnavailableGuild from './Structures/guilds/Unavailable.js'
|
||||
import type AutocompleteInteraction from './Structures/interactions/Autocomplete.js'
|
||||
import type CommandInteraction from './Structures/interactions/Command.js'
|
||||
import type ComponentInteraction from './Structures/interactions/Component.js'
|
||||
import type PingInteraction from './Structures/interactions/Ping.js'
|
||||
import type UnknownInteraction from './Structures/interactions/Unknown.js'
|
||||
import type { IncomingHttpHeaders } from 'node:http'
|
||||
|
||||
export type ApplicationCommandStructure = ChatInputApplicationCommandStructure | MessageApplicationCommandStructure | UserApplicationCommandStructure
|
||||
export type ChatInputApplicationCommand = ApplicationCommand<ApplicationCommandTypes.ChatInput>
|
||||
@@ -885,3 +895,85 @@ export const MessageFlags = {
|
||||
EPHEMERAL: 64,
|
||||
LOADING: 128,
|
||||
}
|
||||
|
||||
export interface EventListeners {
|
||||
channelCreate: [channel: AnyGuildChannel];
|
||||
channelDelete: [channel: AnyChannel];
|
||||
channelPinUpdate: [channel: TextableChannel, timestamp: number, oldTimestamp: number];
|
||||
channelUpdate: [channel: AnyGuildChannel, oldChannel: any];
|
||||
connect: [id: number];
|
||||
debug: [message: string, id?: number];
|
||||
disconnect: [];
|
||||
error: [err: Error, id?: number];
|
||||
guildAvailable: [guild: Guild];
|
||||
guildBanAdd: [guild: Guild, user: User];
|
||||
guildBanRemove: [guild: Guild, user: User];
|
||||
guildCreate: [guild: Guild];
|
||||
guildDelete: [guild: any];
|
||||
guildEmojisUpdate: [guild: any, emojis: Emoji[], oldEmojis: Emoji[] | null];
|
||||
guildMemberAdd: [guild: Guild, member: Member];
|
||||
guildMemberChunk: [guild: Guild, member: Member[]];
|
||||
guildMemberRemove: [guild: Guild, member: Member | any];
|
||||
guildMemberUpdate: [guild: Guild, member: Member, oldMember: any | null];
|
||||
guildRoleCreate: [guild: Guild, role: Role];
|
||||
guildRoleDelete: [guild: Guild, role: Role];
|
||||
guildRoleUpdate: [guild: Guild, role: Role, oldRole: any];
|
||||
guildScheduledEventCreate: [event: any];
|
||||
guildScheduledEventDelete: [event: any];
|
||||
guildScheduledEventUpdate: [event: any, oldEvent: any | null];
|
||||
guildScheduledEventUserAdd: [event: any, user: User | Uncached];
|
||||
guildScheduledEventUserRemove: [event: any, user: User | Uncached];
|
||||
guildStickersUpdate: [guild: any, stickers: Sticker[], oldStickers: Sticker[] | null];
|
||||
guildUnavailable: [guild: UnavailableGuild];
|
||||
guildUpdate: [guild: Guild, oldGuild: any];
|
||||
hello: [trace: string[], id: number];
|
||||
interactionCreate: [interaction: PingInteraction | CommandInteraction | ComponentInteraction | AutocompleteInteraction | UnknownInteraction];
|
||||
inviteCreate: [guild: Guild, invite: Invite];
|
||||
inviteDelete: [guild: Guild, invite: Invite];
|
||||
messageCreate: [message: Message];
|
||||
messageDelete: [message: any];
|
||||
messageDeleteBulk: [messages: any[]];
|
||||
messageReactionAdd: [message: any, emoji: PartialEmoji, reactor: Member | Uncached];
|
||||
messageReactionRemove: [message: any, emoji: PartialEmoji, userID: string];
|
||||
messageReactionRemoveAll: [message: any];
|
||||
messageReactionRemoveEmoji: [message: any, emoji: PartialEmoji];
|
||||
messageUpdate: [message: Message, oldMessage: any | null];
|
||||
presenceUpdate: [other: Member, oldPresence: any | null];
|
||||
rawREST: [request: any];
|
||||
rawWS: [packet: any, id: number];
|
||||
ready: [];
|
||||
shardPreReady: [id: number];
|
||||
stageInstanceCreate: [stageInstance: StageInstance];
|
||||
stageInstanceDelete: [stageInstance: StageInstance];
|
||||
stageInstanceUpdate: [stageInstance: StageInstance, oldStageInstance: any | null];
|
||||
threadCreate: [channel: AnyThreadChannel];
|
||||
threadDelete: [channel: AnyThreadChannel];
|
||||
threadListSync: [guild: Guild, deletedThreads: Array<AnyThreadChannel | Uncached>, activeThreads: AnyThreadChannel[], joinedThreadsMember: ThreadMember[]];
|
||||
threadMembersUpdate: [channel: AnyThreadChannel, addedMembers: ThreadMember[], removedMembers: Array<ThreadMember | Uncached>];
|
||||
threadMemberUpdate: [channel: AnyThreadChannel, member: ThreadMember, oldMember: any];
|
||||
threadUpdate: [channel: AnyThreadChannel, oldChannel: any | null];
|
||||
typingStart: [channel: GuildTextableChannel | Uncached, user: User | Uncached, member: Member]
|
||||
| [channel: PrivateChannel | Uncached, user: User | Uncached, member: null];
|
||||
unavailableGuildCreate: [guild: UnavailableGuild];
|
||||
unknown: [packet: any, id?: number];
|
||||
userUpdate: [user: User, oldUser: PartialUser | null];
|
||||
voiceChannelJoin: [member: Member, channel: AnyVoiceChannel];
|
||||
voiceChannelLeave: [member: Member, channel: AnyVoiceChannel];
|
||||
voiceChannelSwitch: [member: Member, newChannel: AnyVoiceChannel, oldChannel: AnyVoiceChannel];
|
||||
voiceStateUpdate: [member: Member, oldState: any];
|
||||
warn: [message: string, id?: number];
|
||||
webhooksUpdate: [data: any];
|
||||
}
|
||||
|
||||
export interface ClientEvents extends EventListeners {
|
||||
shardDisconnect: [err: Error | undefined, id: number];
|
||||
shardReady: [id: number];
|
||||
shardResume: [id: number];
|
||||
}
|
||||
|
||||
export interface HTTPResponse {
|
||||
code: number;
|
||||
message: string;
|
||||
errors?: HTTPResponse
|
||||
headers: IncomingHttpHeaders
|
||||
}
|
||||
|
||||
86
packages/client/src/utils/DiscordRESTError.ts
Normal file
86
packages/client/src/utils/DiscordRESTError.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { ClientRequest, IncomingHttpHeaders, IncomingMessage } from 'http'
|
||||
import type { HTTPResponse } from '../typings.js'
|
||||
|
||||
export class DiscordRESTError extends Error {
|
||||
code: number = -1
|
||||
req!: ClientRequest
|
||||
res!: IncomingMessage
|
||||
response!: HTTPResponse
|
||||
|
||||
constructor(req: ClientRequest, res: IncomingMessage, response: HTTPResponse, stack: string) {
|
||||
super()
|
||||
|
||||
Object.defineProperty(this, 'req', {
|
||||
enumerable: false,
|
||||
value: req,
|
||||
})
|
||||
Object.defineProperty(this, 'res', {
|
||||
enumerable: false,
|
||||
value: res,
|
||||
})
|
||||
Object.defineProperty(this, 'response', {
|
||||
enumerable: false,
|
||||
value: response,
|
||||
})
|
||||
|
||||
Object.defineProperty(this, 'code', {
|
||||
enumerable: false,
|
||||
value: +response.code || -1,
|
||||
})
|
||||
let message = response.message || 'Unknown error'
|
||||
if (response.errors) {
|
||||
message += '\n ' + this.flattenErrors(response.errors).join('\n ')
|
||||
} else {
|
||||
const errors = this.flattenErrors(response)
|
||||
if (errors.length > 0) {
|
||||
message += '\n ' + errors.join('\n ')
|
||||
}
|
||||
}
|
||||
Object.defineProperty(this, 'message', {
|
||||
enumerable: false,
|
||||
value: message,
|
||||
})
|
||||
|
||||
if (stack) {
|
||||
this.stack = this.name + ': ' + this.message + '\n' + stack
|
||||
} else {
|
||||
Error.captureStackTrace(this, DiscordRESTError)
|
||||
}
|
||||
}
|
||||
|
||||
get headers(): IncomingHttpHeaders {
|
||||
return this.response.headers
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return `${this.constructor.name} [${this.code}]`
|
||||
}
|
||||
|
||||
flattenErrors(errors: HTTPResponse, keyPrefix?: string): string[] {
|
||||
let messages: string[] = []
|
||||
for (const fieldName of Object.keys(errors)) {
|
||||
if (fieldName === 'message' || fieldName === 'code') {
|
||||
continue
|
||||
}
|
||||
|
||||
const prefix = `${keyPrefix ?? ""}${fieldName}`;
|
||||
|
||||
// @ts-expect-error js hack from eris
|
||||
if (errors[fieldName]._errors) {
|
||||
// @ts-expect-error js hack from eris
|
||||
messages = messages.concat(errors[fieldName]._errors.map((obj: any) => `${prefix}: ${obj.message as string}`))
|
||||
// @ts-expect-error js hack from eris
|
||||
} else if (Array.isArray(errors[fieldName])) {
|
||||
// @ts-expect-error js hack from eris
|
||||
messages = messages.concat(errors[fieldName].map((str: string) => `${prefix}: ${str}`))
|
||||
// @ts-expect-error js hack from eris
|
||||
} else if (typeof errors[fieldName] === 'object') {
|
||||
// @ts-expect-error js hack from eris
|
||||
messages = messages.concat(this.flattenErrors(errors[fieldName], `${prefix}.`))
|
||||
}
|
||||
}
|
||||
return messages
|
||||
}
|
||||
}
|
||||
|
||||
export default DiscordRESTError
|
||||
Reference in New Issue
Block a user