mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
247 lines
7.9 KiB
TypeScript
247 lines
7.9 KiB
TypeScript
import {
|
|||
|
|
ApplicationCommand,
|
||
|
|
Channel,
|
||
|
|
Client,
|
||
|
|
DiscordAPIError,
|
||
|
|
RESTJSONErrorCodes as DiscordApiErrors,
|
||
|
|
Guild,
|
||
|
|
GuildMember,
|
||
|
|
Locale,
|
||
|
|
NewsChannel,
|
||
|
|
Role,
|
||
|
|
StageChannel,
|
||
|
|
TextChannel,
|
||
|
|
User,
|
||
|
|
VoiceChannel,
|
||
|
|
} from 'discord.js';
|
||
|
|
|
||
|
|
import { PermissionUtils, RegexUtils } from './index.js';
|
||
|
|
import { Lang } from '../services/index.js';
|
||
|
|
|
||
|
|
const FETCH_MEMBER_LIMIT = 20;
|
||
|
|
const IGNORED_ERRORS = [
|
||
|
|
DiscordApiErrors.UnknownMessage,
|
||
|
|
DiscordApiErrors.UnknownChannel,
|
||
|
|
DiscordApiErrors.UnknownGuild,
|
||
|
|
DiscordApiErrors.UnknownMember,
|
||
|
|
DiscordApiErrors.UnknownUser,
|
||
|
|
DiscordApiErrors.UnknownInteraction,
|
||
|
|
DiscordApiErrors.MissingAccess,
|
||
|
|
];
|
||
|
|
|
||
|
|
export class ClientUtils {
|
||
|
|
public static async getGuild(client: Client, discordId: string): Promise<Guild> {
|
||
|
|
discordId = RegexUtils.discordId(discordId);
|
||
|
|
if (!discordId) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
return await client.guilds.fetch(discordId);
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async getChannel(client: Client, discordId: string): Promise<Channel> {
|
||
|
|
discordId = RegexUtils.discordId(discordId);
|
||
|
|
if (!discordId) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
return await client.channels.fetch(discordId);
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async getUser(client: Client, discordId: string): Promise<User> {
|
||
|
|
discordId = RegexUtils.discordId(discordId);
|
||
|
|
if (!discordId) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
return await client.users.fetch(discordId);
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async findAppCommand(client: Client, name: string): Promise<ApplicationCommand> {
|
||
|
|
let commands = await client.application.commands.fetch();
|
||
|
|
return commands.find(command => command.name === name);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async findMember(guild: Guild, input: string): Promise<GuildMember> {
|
||
|
|
try {
|
||
|
|
let discordId = RegexUtils.discordId(input);
|
||
|
|
if (discordId) {
|
||
|
|
return await guild.members.fetch(discordId);
|
||
|
|
}
|
||
|
|
|
||
|
|
let tag = RegexUtils.tag(input);
|
||
|
|
if (tag) {
|
||
|
|
return (
|
||
|
|
await guild.members.fetch({ query: tag.username, limit: FETCH_MEMBER_LIMIT })
|
||
|
|
).find(member => member.user.discriminator === tag.discriminator);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (await guild.members.fetch({ query: input, limit: 1 })).first();
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async findRole(guild: Guild, input: string): Promise<Role> {
|
||
|
|
try {
|
||
|
|
let discordId = RegexUtils.discordId(input);
|
||
|
|
if (discordId) {
|
||
|
|
return await guild.roles.fetch(discordId);
|
||
|
|
}
|
||
|
|
|
||
|
|
let search = input.trim().toLowerCase().replace(/^@/, '');
|
||
|
|
let roles = await guild.roles.fetch();
|
||
|
|
return (
|
||
|
|
roles.find(role => role.name.toLowerCase() === search) ??
|
||
|
|
roles.find(role => role.name.toLowerCase().includes(search))
|
||
|
|
);
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async findTextChannel(
|
||
|
|
guild: Guild,
|
||
|
|
input: string
|
||
|
|
): Promise<NewsChannel | TextChannel> {
|
||
|
|
try {
|
||
|
|
let discordId = RegexUtils.discordId(input);
|
||
|
|
if (discordId) {
|
||
|
|
let channel = await guild.channels.fetch(discordId);
|
||
|
|
if (channel instanceof NewsChannel || channel instanceof TextChannel) {
|
||
|
|
return channel;
|
||
|
|
} else {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let search = input.trim().toLowerCase().replace(/^#/, '').replaceAll(' ', '-');
|
||
|
|
let channels = [...(await guild.channels.fetch()).values()]
|
||
|
|
.filter(channel => channel instanceof NewsChannel || channel instanceof TextChannel)
|
||
|
|
.map(channel => channel as NewsChannel | TextChannel);
|
||
|
|
return (
|
||
|
|
channels.find(channel => channel.name.toLowerCase() === search) ??
|
||
|
|
channels.find(channel => channel.name.toLowerCase().includes(search))
|
||
|
|
);
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async findVoiceChannel(
|
||
|
|
guild: Guild,
|
||
|
|
input: string
|
||
|
|
): Promise<VoiceChannel | StageChannel> {
|
||
|
|
try {
|
||
|
|
let discordId = RegexUtils.discordId(input);
|
||
|
|
if (discordId) {
|
||
|
|
let channel = await guild.channels.fetch(discordId);
|
||
|
|
if (channel instanceof VoiceChannel || channel instanceof StageChannel) {
|
||
|
|
return channel;
|
||
|
|
} else {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let search = input.trim().toLowerCase().replace(/^#/, '');
|
||
|
|
let channels = [...(await guild.channels.fetch()).values()]
|
||
|
|
.filter(
|
||
|
|
channel => channel instanceof VoiceChannel || channel instanceof StageChannel
|
||
|
|
)
|
||
|
|
.map(channel => channel as VoiceChannel | StageChannel);
|
||
|
|
return (
|
||
|
|
channels.find(channel => channel.name.toLowerCase() === search) ??
|
||
|
|
channels.find(channel => channel.name.toLowerCase().includes(search))
|
||
|
|
);
|
||
|
|
} catch (error) {
|
||
|
|
if (
|
||
|
|
error instanceof DiscordAPIError &&
|
||
|
|
typeof error.code == 'number' &&
|
||
|
|
IGNORED_ERRORS.includes(error.code)
|
||
|
|
) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static async findNotifyChannel(
|
||
|
|
guild: Guild,
|
||
|
|
langCode: Locale
|
||
|
|
): Promise<TextChannel | NewsChannel> {
|
||
|
|
// Prefer the system channel
|
||
|
|
let systemChannel = guild.systemChannel;
|
||
|
|
if (systemChannel && PermissionUtils.canSend(systemChannel, true)) {
|
||
|
|
return systemChannel;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Otherwise look for a bot channel
|
||
|
|
return (await guild.channels.fetch()).find(
|
||
|
|
channel =>
|
||
|
|
(channel instanceof TextChannel || channel instanceof NewsChannel) &&
|
||
|
|
PermissionUtils.canSend(channel, true) &&
|
||
|
|
Lang.getRegex('channelRegexes.bot', langCode).test(channel.name)
|
||
|
|
) as TextChannel | NewsChannel;
|
||
|
|
}
|
||
|
|
}
|