add greeting
add locales
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import type { VoiceChannelsServiceInterface } from "@avocadi/bot-core/entities/channels/voice/voice-channels.service";
|
||||
import { config } from "config";
|
||||
import { ChannelType, type VoiceChannel } from "discord.js";
|
||||
import client from "lib/client";
|
||||
|
||||
export class VoiceChannelsService
|
||||
implements VoiceChannelsServiceInterface<VoiceChannel>
|
||||
{
|
||||
async getVoiceChannelById(channelId: string) {
|
||||
const channel = await client.channels.fetch(channelId);
|
||||
|
||||
if (!channel) {
|
||||
throw new Error(`Channel with id ${channelId} not found`);
|
||||
}
|
||||
|
||||
if (channel.type !== ChannelType.GuildVoice) {
|
||||
throw new Error(`Channel with id ${channelId} is not a voice channel`);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
async createVoiceChannel(name: string) {
|
||||
const guild = await client.guilds.fetch(config.guildId);
|
||||
const channel = await guild.channels.create({
|
||||
name,
|
||||
type: ChannelType.GuildVoice,
|
||||
});
|
||||
return channel;
|
||||
}
|
||||
|
||||
async cloneVoiceChannel(
|
||||
channel: VoiceChannel,
|
||||
options?: { name?: string; position?: number },
|
||||
) {
|
||||
const clonedChannel = await channel.clone({
|
||||
name: options?.name,
|
||||
position: options?.position,
|
||||
});
|
||||
return clonedChannel;
|
||||
}
|
||||
|
||||
async deleteVoiceChannel(channelId: string) {
|
||||
const channel = await this.getVoiceChannelById(channelId);
|
||||
|
||||
await channel.delete();
|
||||
}
|
||||
}
|
||||
|
||||
export const voiceChannelsService = new VoiceChannelsService();
|
||||
32
adapters/discord/src/entities/commands/index.ts
Normal file
32
adapters/discord/src/entities/commands/index.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { CommandsCollection } from "@avocadi/bot-core/entities/commands/commands.entity";
|
||||
import type { Command } from "@avocadi/bot-core/entities/commands/commands.schema";
|
||||
import { SlashCommandBuilder } from "discord.js";
|
||||
import type { z } from "zod";
|
||||
|
||||
const convertCommandToDiscordFormat = (
|
||||
command: z.output<typeof Command>,
|
||||
key: string,
|
||||
) => {
|
||||
const slashCommand = new SlashCommandBuilder()
|
||||
.setName(command.name || key)
|
||||
.setDescription(command.description);
|
||||
|
||||
if (command.options) {
|
||||
command.options.forEach((option) => {
|
||||
slashCommand.addStringOption((opt) =>
|
||||
opt
|
||||
.setName(option.name)
|
||||
.setDescription(option.description)
|
||||
.setRequired(option.required),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return slashCommand;
|
||||
};
|
||||
|
||||
export default function getCommands() {
|
||||
return Object.entries(CommandsCollection).map(([key, command]) =>
|
||||
convertCommandToDiscordFormat(command, key),
|
||||
);
|
||||
}
|
||||
71
adapters/discord/src/entities/messages/messages.service.ts
Normal file
71
adapters/discord/src/entities/messages/messages.service.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import type { MessagesServiceInterface } from "@avocadi/bot-core/entities/messages/messages.service";
|
||||
import { createLogger } from "@avocadi/bot-core/lib/logger";
|
||||
import {
|
||||
type Channel,
|
||||
ChannelType,
|
||||
type DMChannel,
|
||||
type Message,
|
||||
type MessagePayload,
|
||||
type PartialDMChannel,
|
||||
type User,
|
||||
} from "discord.js";
|
||||
import { logChannelService } from "features/log-channel/log-channel.service";
|
||||
import client from "lib/client";
|
||||
|
||||
export class MessagesService
|
||||
implements MessagesServiceInterface<User, Message, Channel, MessagePayload>
|
||||
{
|
||||
private logger = createLogger("MessagesService");
|
||||
|
||||
async sendToUser(userInput: User, message: MessagePayload): Promise<void> {
|
||||
const user = await client.users.fetch(userInput.id);
|
||||
|
||||
if (user) {
|
||||
await user.send(message);
|
||||
} else {
|
||||
this.logger.error(`User with ID ${userInput.id} not found.`);
|
||||
}
|
||||
}
|
||||
|
||||
async logMessage(message: Message): Promise<void> {
|
||||
let recipient: User | null = null;
|
||||
|
||||
if (
|
||||
message.channel.isDMBased() &&
|
||||
message.channel.type !== ChannelType.GroupDM
|
||||
) {
|
||||
const channel = message.channel as DMChannel | PartialDMChannel;
|
||||
|
||||
recipient = channel.recipient;
|
||||
}
|
||||
|
||||
let logMessage: string;
|
||||
|
||||
if (recipient) {
|
||||
logMessage = `<@${message.author.id}> sent a message to <@${recipient.id}>:\n"${message.content}"`;
|
||||
} else {
|
||||
logMessage = `<@${message.author.id}> sent a message:\n"${message.content}"`;
|
||||
}
|
||||
|
||||
await logChannelService.sendLogMessage(logMessage);
|
||||
}
|
||||
|
||||
async sendToChannel(
|
||||
channel: Channel,
|
||||
createMessageInput: MessagePayload,
|
||||
): Promise<void> {
|
||||
const fetchedChannel = await client.channels.fetch(channel.id);
|
||||
|
||||
if (fetchedChannel?.isTextBased() && fetchedChannel.isSendable()) {
|
||||
await fetchedChannel.send(createMessageInput);
|
||||
} else {
|
||||
this.logger.error(
|
||||
`Channel with ID ${channel.id} not found or is not text-based.`,
|
||||
);
|
||||
|
||||
throw new Error("Channel not found or is not text-based.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const messagesService = new MessagesService();
|
||||
33
adapters/discord/src/entities/roles/roles.service.ts
Normal file
33
adapters/discord/src/entities/roles/roles.service.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { RolesServiceInterface } from "@avocadi/bot-core/entities/roles/roles.service";
|
||||
import { createLogger } from "@avocadi/bot-core/lib/logger";
|
||||
import type { GuildMember } from "discord.js";
|
||||
|
||||
export class RolesService implements RolesServiceInterface<GuildMember> {
|
||||
private logger = createLogger("RolesService");
|
||||
|
||||
async assignRole(user: GuildMember, role: string) {
|
||||
const roleToAssign = user.guild.roles.cache.find((r) => r.name === role);
|
||||
if (!roleToAssign) {
|
||||
this.logger.error(`Role ${role} not found in guild ${user.guild.name}.`);
|
||||
return;
|
||||
}
|
||||
await user.roles.add(roleToAssign);
|
||||
}
|
||||
|
||||
async removeRole(user: GuildMember, role: string) {
|
||||
const roleToRemove = user.guild.roles.cache.find((r) => r.name === role);
|
||||
if (!roleToRemove) {
|
||||
this.logger.error(`Role ${role} not found in guild ${user.guild.name}.`);
|
||||
return;
|
||||
}
|
||||
await user.roles.remove(roleToRemove);
|
||||
}
|
||||
|
||||
async getRoles(user: GuildMember) {
|
||||
return user.roles.cache.map((role) => role.name);
|
||||
}
|
||||
|
||||
async hasRole(user: GuildMember, role: string) {
|
||||
return user.roles.cache.some((r) => r.name === role);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user