mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-05 14:36:09 +00:00
feat: guild bans, formatter and minor functionality changes. (#203)
* fix(Colors#bold): bold returning weird values * chore: testing something * fix(Parsers): optionsParser & argsParser were being overriden by default options * revert(colors): mistakenly pushed a unplanned change * feat(Formatter): add a formatter class to add support to discord markdown, unix and etc * chore: set exports for formatter class * feat(AllGuildVoiceChannels): new type for all guild based voice channels * feat(VoiceChannel#members): returns a list of members in the voice channel * chore: small patch to voice channel methods * feat(GuildBans): addition of bans into seyfert * chore: request changes - incomplete * fix(BanShorter#bulkCreate): fix method return, bulk-bans returns stats * feat(GuildBan#methods): all methods added on the guild ban structure * chore: missed some, here pushed them * chore: requested change --------- Co-authored-by: NotAditya69 <90441096+NotAditya69@users.noreply.github.com>
This commit is contained in:
parent
37dfaef407
commit
390953082b
@ -43,7 +43,8 @@
|
|||||||
"noUselessConstructor": "off",
|
"noUselessConstructor": "off",
|
||||||
"noThisInStatic": "off",
|
"noThisInStatic": "off",
|
||||||
"noExcessiveCognitiveComplexity": "off",
|
"noExcessiveCognitiveComplexity": "off",
|
||||||
"noVoid": "off"
|
"noVoid": "off",
|
||||||
|
"noStaticOnlyClass": "off"
|
||||||
},
|
},
|
||||||
"a11y": {
|
"a11y": {
|
||||||
"all": false
|
"all": false
|
||||||
|
@ -84,6 +84,8 @@ import type {
|
|||||||
RESTPatchAPIGuildWidgetSettingsResult,
|
RESTPatchAPIGuildWidgetSettingsResult,
|
||||||
RESTPostAPIAutoModerationRuleJSONBody,
|
RESTPostAPIAutoModerationRuleJSONBody,
|
||||||
RESTPostAPIAutoModerationRuleResult,
|
RESTPostAPIAutoModerationRuleResult,
|
||||||
|
RESTPostAPIGuildBulkBanJSONBody,
|
||||||
|
RESTPostAPIGuildBulkBanResult,
|
||||||
RESTPostAPIGuildChannelJSONBody,
|
RESTPostAPIGuildChannelJSONBody,
|
||||||
RESTPostAPIGuildChannelResult,
|
RESTPostAPIGuildChannelResult,
|
||||||
RESTPostAPIGuildEmojiJSONBody,
|
RESTPostAPIGuildEmojiJSONBody,
|
||||||
@ -233,6 +235,11 @@ export interface GuildRoutes {
|
|||||||
delete(args?: RestArguments<ProxyRequestMethod.Delete>): Promise<RESTDeleteAPIGuildBanResult>;
|
delete(args?: RestArguments<ProxyRequestMethod.Delete>): Promise<RESTDeleteAPIGuildBanResult>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
'bulk-bans': {
|
||||||
|
post(
|
||||||
|
args: RestArguments<ProxyRequestMethod.Post, RESTPostAPIGuildBulkBanJSONBody>,
|
||||||
|
): Promise<RESTPostAPIGuildBulkBanResult>;
|
||||||
|
};
|
||||||
mfa: {
|
mfa: {
|
||||||
post(
|
post(
|
||||||
args: RestArguments<ProxyRequestMethod.Post, RESTPostAPIGuildsMFAJSONBody>,
|
args: RestArguments<ProxyRequestMethod.Post, RESTPostAPIGuildsMFAJSONBody>,
|
||||||
|
24
src/cache/index.ts
vendored
24
src/cache/index.ts
vendored
@ -14,6 +14,7 @@ import { StageInstances } from './resources/stage-instances';
|
|||||||
import { Stickers } from './resources/stickers';
|
import { Stickers } from './resources/stickers';
|
||||||
import { Threads } from './resources/threads';
|
import { Threads } from './resources/threads';
|
||||||
import { VoiceStates } from './resources/voice-states';
|
import { VoiceStates } from './resources/voice-states';
|
||||||
|
import { Bans } from './resources/bans';
|
||||||
|
|
||||||
import { ChannelType, GatewayIntentBits, type GatewayDispatchPayload } from 'discord-api-types/v10';
|
import { ChannelType, GatewayIntentBits, type GatewayDispatchPayload } from 'discord-api-types/v10';
|
||||||
import type { InternalOptions, UsingClient } from '../commands';
|
import type { InternalOptions, UsingClient } from '../commands';
|
||||||
@ -36,7 +37,8 @@ export type GuildRelated =
|
|||||||
| 'presences'
|
| 'presences'
|
||||||
| 'stageInstances'
|
| 'stageInstances'
|
||||||
| 'overwrites'
|
| 'overwrites'
|
||||||
| 'messages';
|
| 'messages'
|
||||||
|
| 'bans';
|
||||||
|
|
||||||
// ClientBased
|
// ClientBased
|
||||||
export type NonGuildBased = 'users' | 'guilds';
|
export type NonGuildBased = 'users' | 'guilds';
|
||||||
@ -58,6 +60,8 @@ export type CachedEvents =
|
|||||||
| 'GUILD_ROLE_CREATE'
|
| 'GUILD_ROLE_CREATE'
|
||||||
| 'GUILD_ROLE_UPDATE'
|
| 'GUILD_ROLE_UPDATE'
|
||||||
| 'GUILD_ROLE_DELETE'
|
| 'GUILD_ROLE_DELETE'
|
||||||
|
| 'GUILD_BAN_ADD'
|
||||||
|
| 'GUILD_BAN_REMOVE'
|
||||||
| 'GUILD_EMOJIS_UPDATE'
|
| 'GUILD_EMOJIS_UPDATE'
|
||||||
| 'GUILD_STICKERS_UPDATE'
|
| 'GUILD_STICKERS_UPDATE'
|
||||||
| 'GUILD_MEMBER_ADD'
|
| 'GUILD_MEMBER_ADD'
|
||||||
@ -93,6 +97,7 @@ export class Cache {
|
|||||||
presences?: Presences;
|
presences?: Presences;
|
||||||
stageInstances?: StageInstances;
|
stageInstances?: StageInstances;
|
||||||
messages?: Messages;
|
messages?: Messages;
|
||||||
|
bans?: Bans;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public intents: number,
|
public intents: number,
|
||||||
@ -144,6 +149,9 @@ export class Cache {
|
|||||||
if (!this.disabledCache.includes('messages')) {
|
if (!this.disabledCache.includes('messages')) {
|
||||||
this.messages = new Messages(this, client);
|
this.messages = new Messages(this, client);
|
||||||
}
|
}
|
||||||
|
if (!this.disabledCache.includes('bans')) {
|
||||||
|
this.bans = new Bans(this, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@ -163,6 +171,7 @@ export class Cache {
|
|||||||
this.threads?.__setClient(client);
|
this.threads?.__setClient(client);
|
||||||
this.stageInstances?.__setClient(client);
|
this.stageInstances?.__setClient(client);
|
||||||
this.messages?.__setClient(client);
|
this.messages?.__setClient(client);
|
||||||
|
this.bans?.__setClient(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
flush(): ReturnCache<void> {
|
flush(): ReturnCache<void> {
|
||||||
@ -206,6 +215,10 @@ export class Cache {
|
|||||||
return this.hasIntent('DirectMessages');
|
return this.hasIntent('DirectMessages');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasBansIntent() {
|
||||||
|
return this.hasIntent('GuildBans');
|
||||||
|
}
|
||||||
|
|
||||||
async bulkGet(
|
async bulkGet(
|
||||||
keys: (
|
keys: (
|
||||||
| readonly [
|
| readonly [
|
||||||
@ -246,6 +259,7 @@ export class Cache {
|
|||||||
case 'users':
|
case 'users':
|
||||||
case 'guilds':
|
case 'guilds':
|
||||||
case 'overwrites':
|
case 'overwrites':
|
||||||
|
case 'bans':
|
||||||
case 'messages':
|
case 'messages':
|
||||||
{
|
{
|
||||||
if (!allData[type]) {
|
if (!allData[type]) {
|
||||||
@ -313,6 +327,7 @@ export class Cache {
|
|||||||
case 'stageInstances':
|
case 'stageInstances':
|
||||||
case 'emojis':
|
case 'emojis':
|
||||||
case 'overwrites':
|
case 'overwrites':
|
||||||
|
case 'bans':
|
||||||
case 'messages':
|
case 'messages':
|
||||||
{
|
{
|
||||||
if (!this[type]?.filter(data, id, guildId)) continue;
|
if (!this[type]?.filter(data, id, guildId)) continue;
|
||||||
@ -404,6 +419,7 @@ export class Cache {
|
|||||||
case 'stageInstances':
|
case 'stageInstances':
|
||||||
case 'emojis':
|
case 'emojis':
|
||||||
case 'overwrites':
|
case 'overwrites':
|
||||||
|
case 'bans':
|
||||||
case 'messages':
|
case 'messages':
|
||||||
{
|
{
|
||||||
if (!this[type]?.filter(data, id, guildId)) continue;
|
if (!this[type]?.filter(data, id, guildId)) continue;
|
||||||
@ -500,6 +516,12 @@ export class Cache {
|
|||||||
case 'GUILD_ROLE_DELETE':
|
case 'GUILD_ROLE_DELETE':
|
||||||
await this.roles?.remove(event.d.role_id, event.d.guild_id);
|
await this.roles?.remove(event.d.role_id, event.d.guild_id);
|
||||||
break;
|
break;
|
||||||
|
case 'GUILD_BAN_ADD':
|
||||||
|
await this.bans?.set(event.d.user.id, event.d.guild_id, event.d);
|
||||||
|
break;
|
||||||
|
case 'GUILD_BAN_REMOVE':
|
||||||
|
await this.bans?.remove(event.d.user.id, event.d.guild_id);
|
||||||
|
break;
|
||||||
case 'GUILD_EMOJIS_UPDATE':
|
case 'GUILD_EMOJIS_UPDATE':
|
||||||
await this.emojis?.remove(await this.emojis?.keys(event.d.guild_id), event.d.guild_id);
|
await this.emojis?.remove(await this.emojis?.keys(event.d.guild_id), event.d.guild_id);
|
||||||
await this.emojis?.set(
|
await this.emojis?.set(
|
||||||
|
46
src/cache/resources/bans.ts
vendored
Normal file
46
src/cache/resources/bans.ts
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import type { APIBan } from 'discord-api-types/v10';
|
||||||
|
import type { ReturnCache } from '../..';
|
||||||
|
import { fakePromise } from '../../common';
|
||||||
|
import { GuildBasedResource } from './default/guild-based';
|
||||||
|
import { GuildBan } from '../../structures/GuildBan';
|
||||||
|
export class Bans extends GuildBasedResource {
|
||||||
|
namespace = 'ban';
|
||||||
|
|
||||||
|
//@ts-expect-error
|
||||||
|
filter(data: APIBan, id: string, guild_id: string) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
override parse(data: any, key: string, guild_id: string) {
|
||||||
|
const { user, ...rest } = super.parse(data, data.user?.id ?? key, guild_id);
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
override get(id: string, guild: string): ReturnCache<GuildBan | undefined> {
|
||||||
|
return fakePromise(super.get(id, guild)).then(rawBan =>
|
||||||
|
rawBan ? new GuildBan(this.client, rawBan, guild) : undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
override bulk(ids: string[], guild: string): ReturnCache<GuildBan[]> {
|
||||||
|
return fakePromise(super.bulk(ids, guild)).then(
|
||||||
|
bans =>
|
||||||
|
bans
|
||||||
|
.map(rawBan => {
|
||||||
|
return rawBan ? new GuildBan(this.client, rawBan, guild) : undefined;
|
||||||
|
})
|
||||||
|
.filter(Boolean) as GuildBan[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
override values(guild: string): ReturnCache<GuildBan[]> {
|
||||||
|
return fakePromise(super.values(guild)).then(
|
||||||
|
bans =>
|
||||||
|
bans
|
||||||
|
.map(rawBan => {
|
||||||
|
return rawBan ? new GuildBan(this.client, rawBan, guild) : undefined;
|
||||||
|
})
|
||||||
|
.filter(Boolean) as GuildBan[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,11 @@ import type {
|
|||||||
RegisteredMiddlewares,
|
RegisteredMiddlewares,
|
||||||
UsingClient,
|
UsingClient,
|
||||||
} from '../commands';
|
} from '../commands';
|
||||||
import { IgnoreCommand, type InferWithPrefix, type MiddlewareContext } from '../commands/applications/shared';
|
import {
|
||||||
|
IgnoreCommand,
|
||||||
|
type InferWithPrefix,
|
||||||
|
type MiddlewareContext,
|
||||||
|
} from '../commands/applications/shared';
|
||||||
import { CommandHandler } from '../commands/handler';
|
import { CommandHandler } from '../commands/handler';
|
||||||
import {
|
import {
|
||||||
ChannelShorter,
|
ChannelShorter,
|
||||||
@ -33,8 +37,18 @@ import {
|
|||||||
type MakeRequired,
|
type MakeRequired,
|
||||||
} from '../common';
|
} from '../common';
|
||||||
|
|
||||||
import type { LocaleString, RESTPostAPIChannelMessageJSONBody } from 'discord-api-types/rest/v10';
|
import type {
|
||||||
import type { Awaitable, DeepPartial, IntentStrings, OmitInsert, PermissionStrings, When } from '../common/types/util';
|
LocaleString,
|
||||||
|
RESTPostAPIChannelMessageJSONBody,
|
||||||
|
} from 'discord-api-types/rest/v10';
|
||||||
|
import type {
|
||||||
|
Awaitable,
|
||||||
|
DeepPartial,
|
||||||
|
IntentStrings,
|
||||||
|
OmitInsert,
|
||||||
|
PermissionStrings,
|
||||||
|
When,
|
||||||
|
} from '../common/types/util';
|
||||||
import { ComponentHandler } from '../components/handler';
|
import { ComponentHandler } from '../components/handler';
|
||||||
import { LangsHandler } from '../langs/handler';
|
import { LangsHandler } from '../langs/handler';
|
||||||
import type {
|
import type {
|
||||||
@ -45,8 +59,14 @@ import type {
|
|||||||
ModalSubmitInteraction,
|
ModalSubmitInteraction,
|
||||||
UserCommandInteraction,
|
UserCommandInteraction,
|
||||||
} from '../structures';
|
} from '../structures';
|
||||||
import type { ComponentCommand, ComponentContext, ModalCommand, ModalContext } from '../components';
|
import type {
|
||||||
|
ComponentCommand,
|
||||||
|
ComponentContext,
|
||||||
|
ModalCommand,
|
||||||
|
ModalContext,
|
||||||
|
} from '../components';
|
||||||
import { promises } from 'node:fs';
|
import { promises } from 'node:fs';
|
||||||
|
import { BanShorter } from '../common/shorters/bans';
|
||||||
|
|
||||||
export class BaseClient {
|
export class BaseClient {
|
||||||
rest!: ApiHandler;
|
rest!: ApiHandler;
|
||||||
@ -63,6 +83,7 @@ export class BaseClient {
|
|||||||
reactions = new ReactionShorter(this);
|
reactions = new ReactionShorter(this);
|
||||||
emojis = new EmojiShorter(this);
|
emojis = new EmojiShorter(this);
|
||||||
threads = new ThreadShorter(this);
|
threads = new ThreadShorter(this);
|
||||||
|
bans = new BanShorter(this);
|
||||||
interactions = new InteractionShorter(this);
|
interactions = new InteractionShorter(this);
|
||||||
|
|
||||||
debugger?: Logger;
|
debugger?: Logger;
|
||||||
@ -79,7 +100,10 @@ export class BaseClient {
|
|||||||
private _botId?: string;
|
private _botId?: string;
|
||||||
middlewares?: Record<string, MiddlewareContext>;
|
middlewares?: Record<string, MiddlewareContext>;
|
||||||
|
|
||||||
protected static assertString(value: unknown, message?: string): asserts value is string {
|
protected static assertString(
|
||||||
|
value: unknown,
|
||||||
|
message?: string
|
||||||
|
): asserts value is string {
|
||||||
if (!(typeof value === 'string' && value !== '')) {
|
if (!(typeof value === 'string' && value !== '')) {
|
||||||
throw new Error(message ?? 'Value is not a string');
|
throw new Error(message ?? 'Value is not a string');
|
||||||
}
|
}
|
||||||
@ -99,43 +123,94 @@ export class BaseClient {
|
|||||||
{
|
{
|
||||||
commands: {
|
commands: {
|
||||||
defaults: {
|
defaults: {
|
||||||
onRunError(context: CommandContext<any>, error: unknown): any {
|
onRunError(
|
||||||
context.client.logger.fatal(`${context.command.name}.<onRunError>`, context.author.id, error);
|
context: CommandContext<any>,
|
||||||
|
error: unknown
|
||||||
|
): any {
|
||||||
|
context.client.logger.fatal(
|
||||||
|
`${context.command.name}.<onRunError>`,
|
||||||
|
context.author.id,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onOptionsError(context: CommandContext<{}, never>, metadata: OnOptionsReturnObject): any {
|
onOptionsError(
|
||||||
context.client.logger.fatal(`${context.command.name}.<onOptionsError>`, context.author.id, metadata);
|
context: CommandContext<{}, never>,
|
||||||
|
metadata: OnOptionsReturnObject
|
||||||
|
): any {
|
||||||
|
context.client.logger.fatal(
|
||||||
|
`${context.command.name}.<onOptionsError>`,
|
||||||
|
context.author.id,
|
||||||
|
metadata
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onMiddlewaresError(context: CommandContext<{}, never>, error: string): any {
|
onMiddlewaresError(
|
||||||
context.client.logger.fatal(`${context.command.name}.<onMiddlewaresError>`, context.author.id, error);
|
context: CommandContext<{}, never>,
|
||||||
|
error: string
|
||||||
|
): any {
|
||||||
|
context.client.logger.fatal(
|
||||||
|
`${context.command.name}.<onMiddlewaresError>`,
|
||||||
|
context.author.id,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onBotPermissionsFail(context: CommandContext<{}, never>, permissions: PermissionStrings): any {
|
onBotPermissionsFail(
|
||||||
|
context: CommandContext<{}, never>,
|
||||||
|
permissions: PermissionStrings
|
||||||
|
): any {
|
||||||
context.client.logger.fatal(
|
context.client.logger.fatal(
|
||||||
`${context.command.name}.<onBotPermissionsFail>`,
|
`${context.command.name}.<onBotPermissionsFail>`,
|
||||||
context.author.id,
|
context.author.id,
|
||||||
permissions,
|
permissions
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onPermissionsFail(context: CommandContext<{}, never>, permissions: PermissionStrings): any {
|
onPermissionsFail(
|
||||||
|
context: CommandContext<{}, never>,
|
||||||
|
permissions: PermissionStrings
|
||||||
|
): any {
|
||||||
context.client.logger.fatal(
|
context.client.logger.fatal(
|
||||||
`${context.command.name}.<onPermissionsFail>`,
|
`${context.command.name}.<onPermissionsFail>`,
|
||||||
context.author.id,
|
context.author.id,
|
||||||
permissions,
|
permissions
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onInternalError(client: UsingClient, command: Command, error?: unknown): any {
|
onInternalError(
|
||||||
client.logger.fatal(`${command.name}.<onInternalError>`, error);
|
client: UsingClient,
|
||||||
|
command: Command,
|
||||||
|
error?: unknown
|
||||||
|
): any {
|
||||||
|
client.logger.fatal(
|
||||||
|
`${command.name}.<onInternalError>`,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
defaults: {
|
defaults: {
|
||||||
onRunError(context: ComponentContext, error: unknown): any {
|
onRunError(
|
||||||
context.client.logger.fatal('ComponentCommand.<onRunError>', context.author.id, error);
|
context: ComponentContext,
|
||||||
|
error: unknown
|
||||||
|
): any {
|
||||||
|
context.client.logger.fatal(
|
||||||
|
'ComponentCommand.<onRunError>',
|
||||||
|
context.author.id,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onMiddlewaresError(context: ComponentContext, error: string): any {
|
onMiddlewaresError(
|
||||||
context.client.logger.fatal('ComponentCommand.<onMiddlewaresError>', context.author.id, error);
|
context: ComponentContext,
|
||||||
|
error: string
|
||||||
|
): any {
|
||||||
|
context.client.logger.fatal(
|
||||||
|
'ComponentCommand.<onMiddlewaresError>',
|
||||||
|
context.author.id,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onInternalError(client: UsingClient, error?: unknown): any {
|
onInternalError(
|
||||||
|
client: UsingClient,
|
||||||
|
error?: unknown
|
||||||
|
): any {
|
||||||
client.logger.fatal(error);
|
client.logger.fatal(error);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -143,18 +218,32 @@ export class BaseClient {
|
|||||||
modals: {
|
modals: {
|
||||||
defaults: {
|
defaults: {
|
||||||
onRunError(context: ModalContext, error: unknown): any {
|
onRunError(context: ModalContext, error: unknown): any {
|
||||||
context.client.logger.fatal('ComponentCommand.<onRunError>', context.author.id, error);
|
context.client.logger.fatal(
|
||||||
|
'ComponentCommand.<onRunError>',
|
||||||
|
context.author.id,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onMiddlewaresError(context: ModalContext, error: string): any {
|
onMiddlewaresError(
|
||||||
context.client.logger.fatal('ComponentCommand.<onMiddlewaresError>', context.author.id, error);
|
context: ModalContext,
|
||||||
|
error: string
|
||||||
|
): any {
|
||||||
|
context.client.logger.fatal(
|
||||||
|
'ComponentCommand.<onMiddlewaresError>',
|
||||||
|
context.author.id,
|
||||||
|
error
|
||||||
|
);
|
||||||
},
|
},
|
||||||
onInternalError(client: UsingClient, error?: unknown): any {
|
onInternalError(
|
||||||
|
client: UsingClient,
|
||||||
|
error?: unknown
|
||||||
|
): any {
|
||||||
client.logger.fatal(error);
|
client.logger.fatal(error);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} satisfies BaseClientOptions,
|
} satisfies BaseClientOptions,
|
||||||
options,
|
options
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +252,9 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get botId() {
|
get botId() {
|
||||||
return this._botId ?? BaseClient.getBotIdFromToken(this.rest.options.token);
|
return (
|
||||||
|
this._botId ?? BaseClient.getBotIdFromToken(this.rest.options.token)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
set applicationId(id: string) {
|
set applicationId(id: string) {
|
||||||
@ -178,7 +269,13 @@ export class BaseClient {
|
|||||||
return new Router(this.rest).createProxy();
|
return new Router(this.rest).createProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
setServices({ rest, cache, langs, middlewares, handlers }: ServicesOptions) {
|
setServices({
|
||||||
|
rest,
|
||||||
|
cache,
|
||||||
|
langs,
|
||||||
|
middlewares,
|
||||||
|
handlers,
|
||||||
|
}: ServicesOptions) {
|
||||||
if (rest) {
|
if (rest) {
|
||||||
this.rest = rest;
|
this.rest = rest;
|
||||||
}
|
}
|
||||||
@ -187,7 +284,7 @@ export class BaseClient {
|
|||||||
this.cache?.intents ?? 0,
|
this.cache?.intents ?? 0,
|
||||||
cache?.adapter ?? this.cache?.adapter ?? new MemoryAdapter(),
|
cache?.adapter ?? this.cache?.adapter ?? new MemoryAdapter(),
|
||||||
cache.disabledCache ?? this.cache?.disabledCache ?? [],
|
cache.disabledCache ?? this.cache?.disabledCache ?? [],
|
||||||
this,
|
this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (middlewares) {
|
if (middlewares) {
|
||||||
@ -199,7 +296,9 @@ export class BaseClient {
|
|||||||
this.components = undefined;
|
this.components = undefined;
|
||||||
} else if (typeof handlers.components === 'function') {
|
} else if (typeof handlers.components === 'function') {
|
||||||
this.components ??= new ComponentHandler(this.logger, this);
|
this.components ??= new ComponentHandler(this.logger, this);
|
||||||
this.components.setHandlers({ callback: handlers.components });
|
this.components.setHandlers({
|
||||||
|
callback: handlers.components,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.components = handlers.components;
|
this.components = handlers.components;
|
||||||
}
|
}
|
||||||
@ -227,7 +326,8 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
if (langs) {
|
if (langs) {
|
||||||
if (langs.default) this.langs!.defaultLang = langs.default;
|
if (langs.default) this.langs!.defaultLang = langs.default;
|
||||||
if (langs.aliases) this.langs!.aliases = Object.entries(langs.aliases);
|
if (langs.aliases)
|
||||||
|
this.langs!.aliases = Object.entries(langs.aliases);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,13 +341,20 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(
|
async start(
|
||||||
options: Pick<DeepPartial<StartOptions>, 'langsDir' | 'commandsDir' | 'connection' | 'token' | 'componentsDir'> = {
|
options: Pick<
|
||||||
|
DeepPartial<StartOptions>,
|
||||||
|
| 'langsDir'
|
||||||
|
| 'commandsDir'
|
||||||
|
| 'connection'
|
||||||
|
| 'token'
|
||||||
|
| 'componentsDir'
|
||||||
|
> = {
|
||||||
token: undefined,
|
token: undefined,
|
||||||
langsDir: undefined,
|
langsDir: undefined,
|
||||||
commandsDir: undefined,
|
commandsDir: undefined,
|
||||||
connection: undefined,
|
connection: undefined,
|
||||||
componentsDir: undefined,
|
componentsDir: undefined,
|
||||||
},
|
}
|
||||||
) {
|
) {
|
||||||
await this.loadLangs(options.langsDir);
|
await this.loadLangs(options.langsDir);
|
||||||
await this.loadCommands(options.commandsDir);
|
await this.loadCommands(options.commandsDir);
|
||||||
@ -278,21 +385,32 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shouldUploadCommands(cachePath: string) {
|
shouldUploadCommands(cachePath: string) {
|
||||||
return this.commands!.shouldUpload(cachePath).then(async should => {
|
return this.commands!.shouldUpload(cachePath).then(async (should) => {
|
||||||
if (should) await promises.writeFile(cachePath, JSON.stringify(this.commands!.values.map(x => x.toJSON())));
|
if (should)
|
||||||
|
await promises.writeFile(
|
||||||
|
cachePath,
|
||||||
|
JSON.stringify(this.commands!.values.map((x) => x.toJSON()))
|
||||||
|
);
|
||||||
return should;
|
return should;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadCommands(applicationId?: string) {
|
async uploadCommands(applicationId?: string) {
|
||||||
applicationId ??= await this.getRC().then(x => x.applicationId ?? this.applicationId);
|
applicationId ??= await this.getRC().then(
|
||||||
|
(x) => x.applicationId ?? this.applicationId
|
||||||
|
);
|
||||||
BaseClient.assertString(applicationId, 'applicationId is not a string');
|
BaseClient.assertString(applicationId, 'applicationId is not a string');
|
||||||
|
|
||||||
const commands = this.commands!.values;
|
const commands = this.commands!.values;
|
||||||
const filter = filterSplit(commands, command => !command.guildId);
|
const filter = filterSplit(commands, (command) => !command.guildId);
|
||||||
|
|
||||||
await this.proxy.applications(applicationId).commands.put({
|
await this.proxy.applications(applicationId).commands.put({
|
||||||
body: filter.expect.filter(cmd => !('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash).map(x => x.toJSON()),
|
body: filter.expect
|
||||||
|
.filter(
|
||||||
|
(cmd) =>
|
||||||
|
!('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash
|
||||||
|
)
|
||||||
|
.map((x) => x.toJSON()),
|
||||||
});
|
});
|
||||||
|
|
||||||
const guilds = new Set<string>();
|
const guilds = new Set<string>();
|
||||||
@ -309,14 +427,19 @@ export class BaseClient {
|
|||||||
.guilds(guild)
|
.guilds(guild)
|
||||||
.commands.put({
|
.commands.put({
|
||||||
body: filter.never
|
body: filter.never
|
||||||
.filter(cmd => cmd.guildId?.includes(guild) && (!('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash))
|
.filter(
|
||||||
.map(x => x.toJSON()),
|
(cmd) =>
|
||||||
|
cmd.guildId?.includes(guild) &&
|
||||||
|
(!('ignore' in cmd) ||
|
||||||
|
cmd.ignore !== IgnoreCommand.Slash)
|
||||||
|
)
|
||||||
|
.map((x) => x.toJSON()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadCommands(dir?: string) {
|
async loadCommands(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.commands);
|
dir ??= await this.getRC().then((x) => x.commands);
|
||||||
if (dir && this.commands) {
|
if (dir && this.commands) {
|
||||||
await this.commands.load(dir, this);
|
await this.commands.load(dir, this);
|
||||||
this.logger.info('CommandHandler loaded');
|
this.logger.info('CommandHandler loaded');
|
||||||
@ -324,7 +447,7 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadComponents(dir?: string) {
|
async loadComponents(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.components);
|
dir ??= await this.getRC().then((x) => x.components);
|
||||||
if (dir && this.components) {
|
if (dir && this.components) {
|
||||||
await this.components.load(dir);
|
await this.components.load(dir);
|
||||||
this.logger.info('ComponentHandler loaded');
|
this.logger.info('ComponentHandler loaded');
|
||||||
@ -332,7 +455,7 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadLangs(dir?: string) {
|
async loadLangs(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.langs);
|
dir ??= await this.getRC().then((x) => x.langs);
|
||||||
if (dir && this.langs) {
|
if (dir && this.langs) {
|
||||||
await this.langs.load(dir);
|
await this.langs.load(dir);
|
||||||
this.logger.info('LangsHandler loaded');
|
this.logger.info('LangsHandler loaded');
|
||||||
@ -344,23 +467,37 @@ export class BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRC<
|
async getRC<
|
||||||
T extends InternalRuntimeConfigHTTP | InternalRuntimeConfig = InternalRuntimeConfigHTTP | InternalRuntimeConfig,
|
T extends InternalRuntimeConfigHTTP | InternalRuntimeConfig =
|
||||||
|
| InternalRuntimeConfigHTTP
|
||||||
|
| InternalRuntimeConfig
|
||||||
>() {
|
>() {
|
||||||
const seyfertConfig = (BaseClient._seyfertConfig ||
|
const seyfertConfig = (BaseClient._seyfertConfig ||
|
||||||
(await this.options.getRC?.()) ||
|
(await this.options.getRC?.()) ||
|
||||||
(await magicImport(join(process.cwd(), 'seyfert.config.js')).then(x => x.default ?? x))) as T;
|
(await magicImport(join(process.cwd(), 'seyfert.config.js')).then(
|
||||||
|
(x) => x.default ?? x
|
||||||
|
))) as T;
|
||||||
|
|
||||||
const { locations, debug, ...env } = seyfertConfig;
|
const { locations, debug, ...env } = seyfertConfig;
|
||||||
|
|
||||||
const obj = {
|
const obj = {
|
||||||
debug: !!debug,
|
debug: !!debug,
|
||||||
...env,
|
...env,
|
||||||
templates: locations.templates ? join(process.cwd(), locations.base, locations.templates) : undefined,
|
templates: locations.templates
|
||||||
langs: locations.langs ? join(process.cwd(), locations.output, locations.langs) : undefined,
|
? join(process.cwd(), locations.base, locations.templates)
|
||||||
|
: undefined,
|
||||||
|
langs: locations.langs
|
||||||
|
? join(process.cwd(), locations.output, locations.langs)
|
||||||
|
: undefined,
|
||||||
events:
|
events:
|
||||||
'events' in locations && locations.events ? join(process.cwd(), locations.output, locations.events) : undefined,
|
'events' in locations && locations.events
|
||||||
components: locations.components ? join(process.cwd(), locations.output, locations.components) : undefined,
|
? join(process.cwd(), locations.output, locations.events)
|
||||||
commands: locations.commands ? join(process.cwd(), locations.output, locations.commands) : undefined,
|
: undefined,
|
||||||
|
components: locations.components
|
||||||
|
? join(process.cwd(), locations.output, locations.components)
|
||||||
|
: undefined,
|
||||||
|
commands: locations.commands
|
||||||
|
? join(process.cwd(), locations.output, locations.commands)
|
||||||
|
: undefined,
|
||||||
base: join(process.cwd(), locations.base),
|
base: join(process.cwd(), locations.base),
|
||||||
output: join(process.cwd(), locations.output),
|
output: join(process.cwd(), locations.output),
|
||||||
};
|
};
|
||||||
@ -379,7 +516,7 @@ export interface BaseClientOptions {
|
|||||||
| MessageCommandInteraction<boolean>
|
| MessageCommandInteraction<boolean>
|
||||||
| ComponentInteraction
|
| ComponentInteraction
|
||||||
| ModalSubmitInteraction
|
| ModalSubmitInteraction
|
||||||
| When<InferWithPrefix, Message, never>,
|
| When<InferWithPrefix, Message, never>
|
||||||
) => {};
|
) => {};
|
||||||
globalMiddlewares?: readonly (keyof RegisteredMiddlewares)[];
|
globalMiddlewares?: readonly (keyof RegisteredMiddlewares)[];
|
||||||
commands?: {
|
commands?: {
|
||||||
@ -410,7 +547,10 @@ export interface BaseClientOptions {
|
|||||||
onAfterRun?: ModalCommand['onAfterRun'];
|
onAfterRun?: ModalCommand['onAfterRun'];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
allowedMentions?: Omit<NonNullable<RESTPostAPIChannelMessageJSONBody['allowed_mentions']>, 'parse'> & {
|
allowedMentions?: Omit<
|
||||||
|
NonNullable<RESTPostAPIChannelMessageJSONBody['allowed_mentions']>,
|
||||||
|
'parse'
|
||||||
|
> & {
|
||||||
parse?: ('everyone' | 'roles' | 'users')[]; //nice types, d-api
|
parse?: ('everyone' | 'roles' | 'users')[]; //nice types, d-api
|
||||||
};
|
};
|
||||||
getRC?(): Awaitable<InternalRuntimeConfig | InternalRuntimeConfigHTTP>;
|
getRC?(): Awaitable<InternalRuntimeConfig | InternalRuntimeConfigHTTP>;
|
||||||
@ -455,11 +595,17 @@ export type InternalRuntimeConfigHTTP = Omit<
|
|||||||
MakeRequired<RC, 'publicKey' | 'port' | 'applicationId'>,
|
MakeRequired<RC, 'publicKey' | 'port' | 'applicationId'>,
|
||||||
'intents' | 'locations'
|
'intents' | 'locations'
|
||||||
> & { locations: Omit<RC['locations'], 'events'> };
|
> & { locations: Omit<RC['locations'], 'events'> };
|
||||||
export type RuntimeConfigHTTP = Omit<MakeRequired<RC, 'publicKey' | 'applicationId'>, 'intents' | 'locations'> & {
|
export type RuntimeConfigHTTP = Omit<
|
||||||
|
MakeRequired<RC, 'publicKey' | 'applicationId'>,
|
||||||
|
'intents' | 'locations'
|
||||||
|
> & {
|
||||||
locations: Omit<RC['locations'], 'events'>;
|
locations: Omit<RC['locations'], 'events'>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InternalRuntimeConfig = Omit<MakeRequired<RC, 'intents'>, 'publicKey' | 'port'>;
|
export type InternalRuntimeConfig = Omit<
|
||||||
|
MakeRequired<RC, 'intents'>,
|
||||||
|
'publicKey' | 'port'
|
||||||
|
>;
|
||||||
export type RuntimeConfig = OmitInsert<
|
export type RuntimeConfig = OmitInsert<
|
||||||
InternalRuntimeConfig,
|
InternalRuntimeConfig,
|
||||||
'intents',
|
'intents',
|
||||||
@ -476,7 +622,9 @@ export interface ServicesOptions {
|
|||||||
middlewares?: Record<string, MiddlewareContext>;
|
middlewares?: Record<string, MiddlewareContext>;
|
||||||
handlers?: {
|
handlers?: {
|
||||||
components?: ComponentHandler | ComponentHandler['callback'];
|
components?: ComponentHandler | ComponentHandler['callback'];
|
||||||
commands?: CommandHandler | Parameters<CommandHandler['setHandlers']>[0];
|
commands?:
|
||||||
|
| CommandHandler
|
||||||
|
| Parameters<CommandHandler['setHandlers']>[0];
|
||||||
langs?: LangsHandler | LangsHandler['callback'];
|
langs?: LangsHandler | LangsHandler['callback'];
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -26,13 +26,26 @@ import {
|
|||||||
} from '../common';
|
} from '../common';
|
||||||
import { EventHandler } from '../events';
|
import { EventHandler } from '../events';
|
||||||
import { ClientUser } from '../structures';
|
import { ClientUser } from '../structures';
|
||||||
import { ShardManager, properties, type ShardManagerOptions } from '../websocket';
|
import {
|
||||||
|
ShardManager,
|
||||||
|
properties,
|
||||||
|
type ShardManagerOptions,
|
||||||
|
} from '../websocket';
|
||||||
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
|
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
|
||||||
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
|
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
|
||||||
import type { BaseClientOptions, InternalRuntimeConfig, ServicesOptions, StartOptions } from './base';
|
import type {
|
||||||
|
BaseClientOptions,
|
||||||
|
InternalRuntimeConfig,
|
||||||
|
ServicesOptions,
|
||||||
|
StartOptions,
|
||||||
|
} from './base';
|
||||||
import { BaseClient } from './base';
|
import { BaseClient } from './base';
|
||||||
import { onInteractionCreate } from './oninteractioncreate';
|
import { onInteractionCreate } from './oninteractioncreate';
|
||||||
import { defaultArgsParser, defaultOptionsParser, onMessageCreate } from './onmessagecreate';
|
import {
|
||||||
|
defaultArgsParser,
|
||||||
|
defaultOptionsParser,
|
||||||
|
onMessageCreate,
|
||||||
|
} from './onmessagecreate';
|
||||||
import { Collectors } from './collectors';
|
import { Collectors } from './collectors';
|
||||||
|
|
||||||
let parentPort: import('node:worker_threads').MessagePort;
|
let parentPort: import('node:worker_threads').MessagePort;
|
||||||
@ -42,7 +55,10 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
gateway!: ShardManager;
|
gateway!: ShardManager;
|
||||||
me!: If<Ready, ClientUser>;
|
me!: If<Ready, ClientUser>;
|
||||||
declare options: Omit<ClientOptions, 'commands'> & {
|
declare options: Omit<ClientOptions, 'commands'> & {
|
||||||
commands: MakeRequired<NonNullable<ClientOptions['commands']>, 'argsParser' | 'optionsParser'>;
|
commands: MakeRequired<
|
||||||
|
NonNullable<ClientOptions['commands']>,
|
||||||
|
'argsParser' | 'optionsParser'
|
||||||
|
>;
|
||||||
};
|
};
|
||||||
memberUpdateHandler = new MemberUpdateHandler();
|
memberUpdateHandler = new MemberUpdateHandler();
|
||||||
presenceUpdateHandler = new PresenceUpdateHandler();
|
presenceUpdateHandler = new PresenceUpdateHandler();
|
||||||
@ -54,11 +70,14 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
this.options = MergeOptions(
|
this.options = MergeOptions(
|
||||||
{
|
{
|
||||||
commands: {
|
commands: {
|
||||||
argsParser: defaultArgsParser,
|
argsParser:
|
||||||
optionsParser: defaultOptionsParser,
|
options?.commands?.argsParser ?? defaultArgsParser,
|
||||||
|
optionsParser:
|
||||||
|
options?.commands?.optionsParser ??
|
||||||
|
defaultOptionsParser,
|
||||||
},
|
},
|
||||||
} satisfies ClientOptions,
|
} satisfies ClientOptions,
|
||||||
this.options,
|
this.options
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,43 +115,60 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadEvents(dir?: string) {
|
async loadEvents(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.events);
|
dir ??= await this.getRC().then((x) => x.events);
|
||||||
if (dir && this.events) {
|
if (dir && this.events) {
|
||||||
await this.events.load(dir);
|
await this.events.load(dir);
|
||||||
this.logger.info('EventHandler loaded');
|
this.logger.info('EventHandler loaded');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async execute(options: { token?: string; intents?: number } = {}) {
|
protected async execute(
|
||||||
|
options: { token?: string; intents?: number } = {}
|
||||||
|
) {
|
||||||
await super.execute(options);
|
await super.execute(options);
|
||||||
|
|
||||||
const worker_threads = lazyLoadPackage<typeof import('node:worker_threads')>('node:worker_threads');
|
const worker_threads = lazyLoadPackage<
|
||||||
|
typeof import('node:worker_threads')
|
||||||
|
>('node:worker_threads');
|
||||||
|
|
||||||
if (worker_threads?.parentPort) {
|
if (worker_threads?.parentPort) {
|
||||||
parentPort = worker_threads.parentPort;
|
parentPort = worker_threads.parentPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worker_threads?.workerData?.__USING_WATCHER__) {
|
if (worker_threads?.workerData?.__USING_WATCHER__) {
|
||||||
parentPort?.on('message', (data: WatcherPayload | WatcherSendToShard) => {
|
parentPort?.on(
|
||||||
|
'message',
|
||||||
|
(data: WatcherPayload | WatcherSendToShard) => {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'PAYLOAD':
|
case 'PAYLOAD':
|
||||||
this.gateway.options.handlePayload(data.shardId, data.payload);
|
this.gateway.options.handlePayload(
|
||||||
|
data.shardId,
|
||||||
|
data.payload
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 'SEND_TO_SHARD':
|
case 'SEND_TO_SHARD':
|
||||||
this.gateway.send(data.shardId, data.payload);
|
this.gateway.send(data.shardId, data.payload);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
await this.gateway.spawnShards();
|
await this.gateway.spawnShards();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async start(options: Omit<DeepPartial<StartOptions>, 'httpConnection'> = {}, execute = true) {
|
async start(
|
||||||
|
options: Omit<DeepPartial<StartOptions>, 'httpConnection'> = {},
|
||||||
|
execute = true
|
||||||
|
) {
|
||||||
await super.start(options);
|
await super.start(options);
|
||||||
await this.loadEvents(options.eventsDir);
|
await this.loadEvents(options.eventsDir);
|
||||||
|
|
||||||
const { token: tokenRC, intents: intentsRC, debug: debugRC } = await this.getRC<InternalRuntimeConfig>();
|
const {
|
||||||
|
token: tokenRC,
|
||||||
|
intents: intentsRC,
|
||||||
|
debug: debugRC,
|
||||||
|
} = await this.getRC<InternalRuntimeConfig>();
|
||||||
const token = options?.token ?? tokenRC;
|
const token = options?.token ?? tokenRC;
|
||||||
const intents = options?.connection?.intents ?? intentsRC;
|
const intents = options?.connection?.intents ?? intentsRC;
|
||||||
|
|
||||||
@ -149,9 +185,14 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
presence: this.options?.presence,
|
presence: this.options?.presence,
|
||||||
debug: debugRC,
|
debug: debugRC,
|
||||||
shardStart: this.options?.shards?.start,
|
shardStart: this.options?.shards?.start,
|
||||||
shardEnd: this.options?.shards?.end ?? this.options?.shards?.total,
|
shardEnd:
|
||||||
totalShards: this.options?.shards?.total ?? this.options?.shards?.end,
|
this.options?.shards?.end ?? this.options?.shards?.total,
|
||||||
properties: { ...properties, ...this.options?.gateway?.properties },
|
totalShards:
|
||||||
|
this.options?.shards?.total ?? this.options?.shards?.end,
|
||||||
|
properties: {
|
||||||
|
...properties,
|
||||||
|
...this.options?.gateway?.properties,
|
||||||
|
},
|
||||||
compress: this.options?.gateway?.compress,
|
compress: this.options?.gateway?.compress,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -173,29 +214,59 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
if (!this.memberUpdateHandler.check(packet.d)) {
|
if (!this.memberUpdateHandler.check(packet.d)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(
|
||||||
|
packet.t,
|
||||||
|
packet,
|
||||||
|
this as Client<true>,
|
||||||
|
shardId
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 'PRESENCE_UPDATE':
|
case 'PRESENCE_UPDATE':
|
||||||
if (!this.presenceUpdateHandler.check(packet.d as any)) {
|
if (!this.presenceUpdateHandler.check(packet.d as any)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(
|
||||||
|
packet.t,
|
||||||
|
packet,
|
||||||
|
this as Client<true>,
|
||||||
|
shardId
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 'GUILD_CREATE': {
|
case 'GUILD_CREATE': {
|
||||||
if (this.__handleGuilds?.has(packet.d.id)) {
|
if (this.__handleGuilds?.has(packet.d.id)) {
|
||||||
this.__handleGuilds.delete(packet.d.id);
|
this.__handleGuilds.delete(packet.d.id);
|
||||||
if (!this.__handleGuilds.size && [...this.gateway.values()].every(shard => shard.data.session_id)) {
|
if (
|
||||||
await this.events?.runEvent('BOT_READY', this, this.me, -1);
|
!this.__handleGuilds.size &&
|
||||||
|
[...this.gateway.values()].every(
|
||||||
|
(shard) => shard.data.session_id
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
await this.events?.runEvent(
|
||||||
|
'BOT_READY',
|
||||||
|
this,
|
||||||
|
this.me,
|
||||||
|
-1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!this.__handleGuilds.size) delete this.__handleGuilds;
|
if (!this.__handleGuilds.size) delete this.__handleGuilds;
|
||||||
return this.cache.onPacket(packet);
|
return this.cache.onPacket(packet);
|
||||||
}
|
}
|
||||||
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(
|
||||||
|
packet.t,
|
||||||
|
packet,
|
||||||
|
this as Client<true>,
|
||||||
|
shardId
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//rest of the events
|
//rest of the events
|
||||||
default: {
|
default: {
|
||||||
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(
|
||||||
|
packet.t,
|
||||||
|
packet,
|
||||||
|
this as Client<true>,
|
||||||
|
shardId
|
||||||
|
);
|
||||||
switch (packet.t) {
|
switch (packet.t) {
|
||||||
case 'INTERACTION_CREATE':
|
case 'INTERACTION_CREATE':
|
||||||
await onInteractionCreate(this, packet.d, shardId);
|
await onInteractionCreate(this, packet.d, shardId);
|
||||||
@ -209,19 +280,36 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
}
|
}
|
||||||
this.botId = packet.d.user.id;
|
this.botId = packet.d.user.id;
|
||||||
this.applicationId = packet.d.application.id;
|
this.applicationId = packet.d.application.id;
|
||||||
this.me = new ClientUser(this, packet.d.user, packet.d.application) as never;
|
this.me = new ClientUser(
|
||||||
|
this,
|
||||||
|
packet.d.user,
|
||||||
|
packet.d.application
|
||||||
|
) as never;
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
this.__handleGuilds?.size &&
|
this.__handleGuilds?.size &&
|
||||||
(this.gateway.options.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds
|
(this.gateway.options.intents &
|
||||||
|
GatewayIntentBits.Guilds) ===
|
||||||
|
GatewayIntentBits.Guilds
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if ([...this.gateway.values()].every(shard => shard.data.session_id)) {
|
if (
|
||||||
await this.events?.runEvent('BOT_READY', this, this.me, -1);
|
[...this.gateway.values()].every(
|
||||||
|
(shard) => shard.data.session_id
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
await this.events?.runEvent(
|
||||||
|
'BOT_READY',
|
||||||
|
this,
|
||||||
|
this.me,
|
||||||
|
-1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
delete this.__handleGuilds;
|
delete this.__handleGuilds;
|
||||||
}
|
}
|
||||||
this.debugger?.debug(`#${shardId}[${packet.d.user.username}](${this.botId}) is online...`);
|
this.debugger?.debug(
|
||||||
|
`#${shardId}[${packet.d.user.username}](${this.botId}) is online...`
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -243,15 +331,21 @@ export interface ClientOptions extends BaseClientOptions {
|
|||||||
};
|
};
|
||||||
commands?: BaseClientOptions['commands'] & {
|
commands?: BaseClientOptions['commands'] & {
|
||||||
prefix?: (message: Message) => Promise<string[]> | string[];
|
prefix?: (message: Message) => Promise<string[]> | string[];
|
||||||
deferReplyResponse?: (ctx: CommandContext) => Parameters<Message['write']>[0];
|
deferReplyResponse?: (
|
||||||
|
ctx: CommandContext
|
||||||
|
) => Parameters<Message['write']>[0];
|
||||||
reply?: (ctx: CommandContext) => boolean;
|
reply?: (ctx: CommandContext) => boolean;
|
||||||
argsParser?: (content: string, command: SubCommand | Command, message: Message) => Record<string, string>;
|
argsParser?: (
|
||||||
|
content: string,
|
||||||
|
command: SubCommand | Command,
|
||||||
|
message: Message
|
||||||
|
) => Record<string, string>;
|
||||||
optionsParser?: (
|
optionsParser?: (
|
||||||
self: UsingClient,
|
self: UsingClient,
|
||||||
command: Command | SubCommand,
|
command: Command | SubCommand,
|
||||||
message: GatewayMessageCreateDispatchData,
|
message: GatewayMessageCreateDispatchData,
|
||||||
args: Partial<Record<string, string>>,
|
args: Partial<Record<string, string>>,
|
||||||
resolved: MakeRequired<ContextOptionsResolved>,
|
resolved: MakeRequired<ContextOptionsResolved>
|
||||||
) => Awaitable<{
|
) => Awaitable<{
|
||||||
errors: {
|
errors: {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
export * from './it/constants';
|
export * from './it/constants';
|
||||||
export * from './it/utils';
|
export * from './it/utils';
|
||||||
//
|
|
||||||
export * from './it/colors';
|
export * from './it/colors';
|
||||||
export * from './it/logger';
|
export * from './it/logger';
|
||||||
|
export * from './it/formatter';
|
||||||
|
//
|
||||||
export * from './shorters/channels';
|
export * from './shorters/channels';
|
||||||
export * from './shorters/emojis';
|
export * from './shorters/emojis';
|
||||||
export * from './shorters/guilds';
|
export * from './shorters/guilds';
|
||||||
@ -15,6 +16,7 @@ export * from './shorters/users';
|
|||||||
export * from './shorters/threads';
|
export * from './shorters/threads';
|
||||||
export * from './shorters/webhook';
|
export * from './shorters/webhook';
|
||||||
export * from './shorters/interaction';
|
export * from './shorters/interaction';
|
||||||
|
//
|
||||||
export * from './types/options';
|
export * from './types/options';
|
||||||
export * from './types/resolvables';
|
export * from './types/resolvables';
|
||||||
export * from './types/util';
|
export * from './types/util';
|
||||||
|
203
src/common/it/formatter.ts
Normal file
203
src/common/it/formatter.ts
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/**
|
||||||
|
* Represents heading levels.
|
||||||
|
*/
|
||||||
|
export enum HeadingLevel {
|
||||||
|
/**
|
||||||
|
* Represents a level 1 heading. (#)
|
||||||
|
*/
|
||||||
|
H1 = 1,
|
||||||
|
/**
|
||||||
|
* Represents a level 2 heading. (##)
|
||||||
|
*/
|
||||||
|
H2 = 2,
|
||||||
|
/**
|
||||||
|
* Represents a level 3 heading. (###)
|
||||||
|
*/
|
||||||
|
H3 = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents timestamp styles.
|
||||||
|
*/
|
||||||
|
export enum TimestampStyle {
|
||||||
|
/**
|
||||||
|
* Represents a short timestamp style.
|
||||||
|
*/
|
||||||
|
ShortTime = 't',
|
||||||
|
/**
|
||||||
|
* Represents a long timestamp style.
|
||||||
|
*/
|
||||||
|
LongTime = 'T',
|
||||||
|
/**
|
||||||
|
* Represents a short date style.
|
||||||
|
*/
|
||||||
|
ShortDate = 'd',
|
||||||
|
/**
|
||||||
|
* Represents a long date style.
|
||||||
|
*/
|
||||||
|
LongDate = 'D',
|
||||||
|
/**
|
||||||
|
* Represents a short time style.
|
||||||
|
*/
|
||||||
|
ShortDateTime = 'f',
|
||||||
|
/**
|
||||||
|
* Represents a long time style.
|
||||||
|
*/
|
||||||
|
LongDateTime = 'F',
|
||||||
|
/**
|
||||||
|
* Represents a relative time style.
|
||||||
|
*/
|
||||||
|
RelativeTime = 'R',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a message link.
|
||||||
|
*/
|
||||||
|
type MessageLink = `https://discord.com/channels/${string}/${string}/${string}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a timestamp.
|
||||||
|
*/
|
||||||
|
type Timestamp = `<t:${number}:${TimestampStyle}>`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a formatter utility for formatting content.
|
||||||
|
*/
|
||||||
|
export class Formatter {
|
||||||
|
/**
|
||||||
|
* Formats a code block.
|
||||||
|
* @param content The content of the code block.
|
||||||
|
* @param language The language of the code block. Defaults to 'txt'.
|
||||||
|
* @returns The formatted code block.
|
||||||
|
*/
|
||||||
|
static codeBlock(content: string, language = 'txt'): string {
|
||||||
|
return `\`\`\`${language}\n${content}\n\`\`\``;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into inline code.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static inlineCode(content: string): `\`${string}\`` {
|
||||||
|
return `\`${content}\``;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into bold text.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static bold(content: string): `**${string}**` {
|
||||||
|
return `**${content}**`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into italic text.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static italic(content: string): `*${string}*` {
|
||||||
|
return `*${content}*`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into underlined text.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static underline(content: string): `__${string}__` {
|
||||||
|
return `__${content}__`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into strikethrough text.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static strikeThrough(content: string): `~~${string}~~` {
|
||||||
|
return `~~${content}~~`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into a hyperlink.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @param url The URL to hyperlink to.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static hyperlink(content: string, url: string): `[${string}](${string})` {
|
||||||
|
return `[${content}](${url})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into a spoiler.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static spoiler(content: string): `||${string}||` {
|
||||||
|
return `||${content}||`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into a quote.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static blockQuote(content: string): string {
|
||||||
|
return `>>> ${content}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats content into a quote.
|
||||||
|
* @param content The content to format.
|
||||||
|
* @returns The formatted content.
|
||||||
|
*/
|
||||||
|
static quote(content: string): string {
|
||||||
|
return `> ${content}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a message link.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param channelId The ID of the channel.
|
||||||
|
* @param messageId The ID of the message.
|
||||||
|
* @returns The formatted message link.
|
||||||
|
*/
|
||||||
|
static messageLink(guildId: string, channelId: string, messageId: string): MessageLink {
|
||||||
|
return `https://discord.com/channels/${guildId}/${channelId}/${messageId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a header.
|
||||||
|
* @param content The content of the header.
|
||||||
|
* @param level The level of the header. Defaults to 1.
|
||||||
|
* @returns The formatted header.
|
||||||
|
*/
|
||||||
|
static header(content: string, level: HeadingLevel = HeadingLevel.H1): string {
|
||||||
|
return `${'#'.repeat(level)} ${content}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a list.
|
||||||
|
* @param items The items of the list.
|
||||||
|
* @param ordered Whether the list is ordered. Defaults to false.
|
||||||
|
* @returns The formatted list.
|
||||||
|
*/
|
||||||
|
static list(items: string[], ordered = false): string {
|
||||||
|
return items
|
||||||
|
.map((item, index) => {
|
||||||
|
return (ordered ? `${index + 1}. ` : '- ') + item;
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given timestamp into discord unix timestamp format.
|
||||||
|
* @param timestamp The timestamp to format.
|
||||||
|
* @param style The style of the timestamp. Defaults to 't'.
|
||||||
|
* @returns The formatted timestamp.
|
||||||
|
*/
|
||||||
|
static timestamp(timestamp: Date, style: TimestampStyle = TimestampStyle.RelativeTime): Timestamp {
|
||||||
|
return `<t:${Math.floor(timestamp.getTime() / 1000)}:${style}>`;
|
||||||
|
}
|
||||||
|
}
|
86
src/common/shorters/bans.ts
Normal file
86
src/common/shorters/bans.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import type {
|
||||||
|
APIBan,
|
||||||
|
RESTGetAPIGuildBansQuery,
|
||||||
|
RESTPostAPIGuildBulkBanJSONBody,
|
||||||
|
RESTPutAPIGuildBanJSONBody,
|
||||||
|
} from 'discord-api-types/v10';
|
||||||
|
import { BaseShorter } from './base';
|
||||||
|
import { GuildBan } from '../../structures/GuildBan';
|
||||||
|
|
||||||
|
export class BanShorter extends BaseShorter {
|
||||||
|
/**
|
||||||
|
* Bulk creates bans in the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param body The request body for bulk banning members.
|
||||||
|
* @param reason The reason for bulk banning members.
|
||||||
|
*/
|
||||||
|
async bulkCreate(guildId: string, body: RESTPostAPIGuildBulkBanJSONBody, reason?: string) {
|
||||||
|
const bans = await this.client.proxy.guilds(guildId)['bulk-bans'].post({ reason, body });
|
||||||
|
for (const id of bans.banned_users) this.client.cache.members?.removeIfNI('GuildBans', id, guildId);
|
||||||
|
return bans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbans a member from the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param memberId The ID of the member to unban.
|
||||||
|
* @param reason The reason for unbanning the member.
|
||||||
|
*/
|
||||||
|
async remove(guildId: string, memberId: string, reason?: string) {
|
||||||
|
await this.client.proxy.guilds(guildId).bans(memberId).delete({ reason });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bans a member from the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param memberId The ID of the member to ban.
|
||||||
|
* @param body The request body for banning the member.
|
||||||
|
* @param reason The reason for banning the member.
|
||||||
|
*/
|
||||||
|
async create(guildId: string, memberId: string, body?: RESTPutAPIGuildBanJSONBody, reason?: string) {
|
||||||
|
await this.client.proxy.guilds(guildId).bans(memberId).put({ reason, body });
|
||||||
|
await this.client.cache.members?.removeIfNI('GuildBans', memberId, guildId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a ban from the guild.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param userId The ID of the user to fetch.
|
||||||
|
* @param force Whether to force fetching the ban from the API even if it exists in the cache.
|
||||||
|
* @returns A Promise that resolves to the fetched ban.
|
||||||
|
*/
|
||||||
|
async fetch(guildId: string, userId: string, force = false) {
|
||||||
|
let ban;
|
||||||
|
if (!force) {
|
||||||
|
ban = await this.client.cache.bans?.get(userId, guildId);
|
||||||
|
if (ban) return ban;
|
||||||
|
}
|
||||||
|
|
||||||
|
ban = await this.client.proxy.guilds(guildId).bans(userId).get();
|
||||||
|
await this.client.cache.members?.set(ban.user!.id, guildId, ban);
|
||||||
|
return new GuildBan(this.client, ban, guildId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists bans in the guild based on the provided query.
|
||||||
|
* @param guildId The ID of the guild.
|
||||||
|
* @param query The query parameters for listing bans.
|
||||||
|
* @param force Whether to force listing bans from the API even if they exist in the cache.
|
||||||
|
* @returns A Promise that resolves to an array of listed bans.
|
||||||
|
*/
|
||||||
|
async list(guildId: string, query?: RESTGetAPIGuildBansQuery, force = false) {
|
||||||
|
let bans;
|
||||||
|
if (!force) {
|
||||||
|
bans = (await this.client.cache.bans?.values(guildId)) ?? [];
|
||||||
|
if (bans.length) return bans;
|
||||||
|
}
|
||||||
|
bans = await this.client.proxy.guilds(guildId).bans.get({
|
||||||
|
query,
|
||||||
|
});
|
||||||
|
await this.client.cache.bans?.set(
|
||||||
|
bans.map<[string, APIBan]>(x => [x.user!.id, x]),
|
||||||
|
guildId,
|
||||||
|
);
|
||||||
|
return bans.map(m => new GuildBan(this.client, m, guildId));
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from './client/base';
|
} from './client/base';
|
||||||
import type { CustomEventsKeys, ClientNameEvents, EventContext } from './events';
|
import type { CustomEventsKeys, ClientNameEvents, EventContext } from './events';
|
||||||
import { isCloudfareWorker } from './common';
|
import { isCloudfareWorker } from './common';
|
||||||
export { Logger, PermissionStrings, Watcher } from './common';
|
export { Logger, PermissionStrings, Watcher, Formatter } from './common';
|
||||||
//
|
//
|
||||||
export { Collection, LimitedCollection } from './collection';
|
export { Collection, LimitedCollection } from './collection';
|
||||||
//
|
//
|
||||||
|
@ -10,6 +10,7 @@ import { Sticker } from './Sticker';
|
|||||||
import { BaseChannel, WebhookGuildMethods } from './channels';
|
import { BaseChannel, WebhookGuildMethods } from './channels';
|
||||||
import { BaseGuild } from './extra/BaseGuild';
|
import { BaseGuild } from './extra/BaseGuild';
|
||||||
import type { DiscordBase } from './extra/DiscordBase';
|
import type { DiscordBase } from './extra/DiscordBase';
|
||||||
|
import { GuildBan } from './GuildBan';
|
||||||
|
|
||||||
export interface Guild extends ObjectToLower<Omit<APIGuild, 'stickers' | 'emojis' | 'roles'>>, DiscordBase {}
|
export interface Guild extends ObjectToLower<Omit<APIGuild, 'stickers' | 'emojis' | 'roles'>>, DiscordBase {}
|
||||||
export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unknown as ToClass<
|
export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unknown as ToClass<
|
||||||
@ -75,6 +76,7 @@ export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unk
|
|||||||
roles = GuildRole.methods({ client: this.client, guildId: this.id });
|
roles = GuildRole.methods({ client: this.client, guildId: this.id });
|
||||||
channels = BaseChannel.allMethods({ client: this.client, guildId: this.id });
|
channels = BaseChannel.allMethods({ client: this.client, guildId: this.id });
|
||||||
emojis = GuildEmoji.methods({ client: this.client, guildId: this.id });
|
emojis = GuildEmoji.methods({ client: this.client, guildId: this.id });
|
||||||
|
bans = GuildBan.methods({ client: this.client, guildId: this.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Maximun custom guild emojis per level */
|
/** Maximun custom guild emojis per level */
|
||||||
|
49
src/structures/GuildBan.ts
Normal file
49
src/structures/GuildBan.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import type { APIBan, RESTGetAPIGuildBansQuery } from 'discord-api-types/v10';
|
||||||
|
import type { UsingClient } from '../commands';
|
||||||
|
import type { MethodContext, ObjectToLower } from '../common';
|
||||||
|
import { DiscordBase } from './extra/DiscordBase';
|
||||||
|
import type { BanShorter } from '../common/shorters/bans';
|
||||||
|
|
||||||
|
export interface GuildBan extends DiscordBase, ObjectToLower<Omit<APIBan, 'id'>> {}
|
||||||
|
|
||||||
|
export class GuildBan extends DiscordBase {
|
||||||
|
constructor(
|
||||||
|
client: UsingClient,
|
||||||
|
data: APIBan,
|
||||||
|
readonly guildId: string,
|
||||||
|
) {
|
||||||
|
super(client, { ...data, id: data.user.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
create(body?: Parameters<BanShorter['create']>[2], reason?: string) {
|
||||||
|
return this.client.bans.create(this.guildId, this.id, body, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(reason?: string) {
|
||||||
|
return this.client.bans.remove(this.guildId, this.id, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
guild(force = false) {
|
||||||
|
return this.client.guilds.fetch(this.guildId, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(force = false) {
|
||||||
|
return this.client.bans.fetch(this.guildId, this.id, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `<@${this.id}>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static methods({ client, guildId }: MethodContext<{ guildId: string }>) {
|
||||||
|
return {
|
||||||
|
fetch: (userId: string, force = false) => client.bans.fetch(guildId, userId, force),
|
||||||
|
list: (query?: RESTGetAPIGuildBansQuery, force = false) => client.bans.list(guildId, query, force),
|
||||||
|
create: (memberId: string, body?: Parameters<BanShorter['create']>[2], reason?: string) =>
|
||||||
|
client.bans.create(guildId, memberId, body, reason),
|
||||||
|
remove: (memberId: string, reason?: string) => client.bans.remove(guildId, memberId, reason),
|
||||||
|
bulkCreate: (body: Parameters<BanShorter['bulkCreate']>[1], reason?: string) =>
|
||||||
|
client.bans.bulkCreate(guildId, body, reason),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -41,7 +41,7 @@ import type { GuildMember } from './GuildMember';
|
|||||||
import type { GuildRole } from './GuildRole';
|
import type { GuildRole } from './GuildRole';
|
||||||
import { DiscordBase } from './extra/DiscordBase';
|
import { DiscordBase } from './extra/DiscordBase';
|
||||||
import { channelLink } from './extra/functions';
|
import { channelLink } from './extra/functions';
|
||||||
import type { RawFile } from '..';
|
import { Collection, type RawFile } from '..';
|
||||||
|
|
||||||
export class BaseChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> {
|
export class BaseChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> {
|
||||||
declare type: T;
|
declare type: T;
|
||||||
@ -216,9 +216,15 @@ export class MessagesMethods extends DiscordBase {
|
|||||||
return this.client.channels.typing(this.id);
|
return this.client.channels.typing(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
messages = MessagesMethods.messages({ client: this.client, channelId: this.id });
|
messages = MessagesMethods.messages({
|
||||||
|
client: this.client,
|
||||||
|
channelId: this.id,
|
||||||
|
});
|
||||||
pins = MessagesMethods.pins({ client: this.client, channelId: this.id });
|
pins = MessagesMethods.pins({ client: this.client, channelId: this.id });
|
||||||
reactions = MessagesMethods.reactions({ client: this.client, channelId: this.id });
|
reactions = MessagesMethods.reactions({
|
||||||
|
client: this.client,
|
||||||
|
channelId: this.id,
|
||||||
|
});
|
||||||
|
|
||||||
static messages(ctx: MethodContext<{ channelId: string }>) {
|
static messages(ctx: MethodContext<{ channelId: string }>) {
|
||||||
return {
|
return {
|
||||||
@ -265,7 +271,10 @@ export class MessagesMethods extends DiscordBase {
|
|||||||
embeds: body.embeds?.map(x => (x instanceof Embed ? x.toJSON() : x)) ?? undefined,
|
embeds: body.embeds?.map(x => (x instanceof Embed ? x.toJSON() : x)) ?? undefined,
|
||||||
attachments:
|
attachments:
|
||||||
'attachments' in body
|
'attachments' in body
|
||||||
? body.attachments?.map((x, i) => ({ id: i, ...resolveAttachment(x) })) ?? undefined
|
? body.attachments?.map((x, i) => ({
|
||||||
|
id: i,
|
||||||
|
...resolveAttachment(x),
|
||||||
|
})) ?? undefined
|
||||||
: (files?.map((x, id) => ({
|
: (files?.map((x, id) => ({
|
||||||
id,
|
id,
|
||||||
filename: x.name,
|
filename: x.name,
|
||||||
@ -378,10 +387,26 @@ export class VoiceChannelMethods extends DiscordBase {
|
|||||||
const filter = states.filter(state => state.channelId === this.id);
|
const filter = states.filter(state => state.channelId === this.id);
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async members(force?: boolean) {
|
||||||
|
const collection = new Collection<string, GuildMember>();
|
||||||
|
|
||||||
|
const states = await this.states();
|
||||||
|
|
||||||
|
for (const state of states) {
|
||||||
|
const member = await state.member(force);
|
||||||
|
collection.set(member.id, member);
|
||||||
|
}
|
||||||
|
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WebhookGuildMethods extends DiscordBase {
|
export class WebhookGuildMethods extends DiscordBase {
|
||||||
webhooks = WebhookGuildMethods.guild({ client: this.client, guildId: this.id });
|
webhooks = WebhookGuildMethods.guild({
|
||||||
|
client: this.client,
|
||||||
|
guildId: this.id,
|
||||||
|
});
|
||||||
|
|
||||||
static guild(ctx: MethodContext<{ guildId: string }>) {
|
static guild(ctx: MethodContext<{ guildId: string }>) {
|
||||||
return {
|
return {
|
||||||
@ -391,7 +416,10 @@ export class WebhookGuildMethods extends DiscordBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class WebhookChannelMethods extends DiscordBase {
|
export class WebhookChannelMethods extends DiscordBase {
|
||||||
webhooks = WebhookChannelMethods.channel({ client: this.client, channelId: this.id });
|
webhooks = WebhookChannelMethods.channel({
|
||||||
|
client: this.client,
|
||||||
|
channelId: this.id,
|
||||||
|
});
|
||||||
|
|
||||||
static channel(ctx: MethodContext<{ channelId: string }>) {
|
static channel(ctx: MethodContext<{ channelId: string }>) {
|
||||||
return {
|
return {
|
||||||
@ -555,6 +583,7 @@ export type AllGuildChannels =
|
|||||||
|
|
||||||
export type AllTextableChannels = TextGuildChannel | VoiceChannel | DMChannel | NewsChannel | ThreadChannel;
|
export type AllTextableChannels = TextGuildChannel | VoiceChannel | DMChannel | NewsChannel | ThreadChannel;
|
||||||
export type AllGuildTextableChannels = TextGuildChannel | VoiceChannel | NewsChannel | ThreadChannel;
|
export type AllGuildTextableChannels = TextGuildChannel | VoiceChannel | NewsChannel | ThreadChannel;
|
||||||
|
export type AllGuildVoiceChannels = VoiceChannel | StageChannel;
|
||||||
|
|
||||||
export type AllChannels =
|
export type AllChannels =
|
||||||
| BaseChannel<ChannelType>
|
| BaseChannel<ChannelType>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user