Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perguntas Anónimas #62

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
70 changes: 70 additions & 0 deletions application/usecases/readDirectMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Message, Client, MessageEmbed, MessageActionRow, MessageButton } from "discord.js";
import { ChannelSlug } from "../../types";
import QuestionChatService from "./sendMessageToChannel/sendPerguntaToChannel";
import ChatService from "../../domain/service/chatService";
import ChannelResolver from "../../domain/service/channelResolver";

const askedRecently = new Set();
const messageSize = 1500;
class ReadDirectMessageUseCase {
constructor(
private message: Message,
private client: Client,
private channelResolver: ChannelResolver,
private chatService: ChatService,
private questionChatService: QuestionChatService
) {}

async isValid() {
if (askedRecently.has(this.message.author.id) && this.message.channel.type === "DM") {
this.message.channel.send("Ainda não podes enviar outra pergunta. Tenta mais tarde.");
return false;
}
if (this.message.author.id === this.client.user?.id || this.message.channel.type !== "DM") {
return false;
}
if (
this.message.channel.type === "DM" &&
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think there should be a ENUM here for types

this.message.content.startsWith("!pergunta") &&
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️

this.message.content.split(" ").length > 1 &&
this.message.content.length <= messageSize
) {
askedRecently.add(this.message.author.id);
setTimeout(() => {
askedRecently.delete(this.message.author.id);
}, 60000);
return true;
}
this.chatService.sendDirectMessageToUser(
this.message.author.id,
"Por favor usa o seguinte formato:\n!pergunta <mensagem>"
);

return false;
}

async approveMessage(): Promise<void> {
const channelAnonQuestion = this.client.channels.cache.get(this.channelResolver.getBySlug(ChannelSlug.QUESTION));
// const questionChatService: QuestionChatService = new DiscordEmbedService(this.client);
const originalUserId = this.message.author.id;
const sentence = this.message.content.split(" ").slice(1).join(" ");
const buttons = new MessageActionRow().addComponents(
new MessageButton().setLabel("Aprovar").setStyle("SUCCESS").setCustomId(`apr${originalUserId}`),
new MessageButton().setLabel("Eliminar").setStyle("DANGER").setCustomId(`rej${originalUserId}`)
);
const mensagem = new MessageEmbed().setColor("#0099ff").setTitle("Pergunta Anónima").setDescription(sentence);

await this.questionChatService.sendEmbedToChannel(
mensagem,
buttons,
this.channelResolver.getBySlug(ChannelSlug.MOD_CHANNEL)
);

await this.chatService.sendDirectMessageToUser(
this.message.author.id,
`A tua pergunta foi colocada com sucesso.\nApós aprovação poderás visualizar no ${channelAnonQuestion} `
);
}
}

export default ReadDirectMessageUseCase;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { MessageEmbed, MessageActionRow } from "discord.js";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Está a importar coisas específicas do Discord.js. Aqui deveria estar a importar alguma abstração. Podemos discutir isto com o @Adjilino que ele tem lá uns pontos semelhantes também no MR dele.


export default interface SendMessageToChannel {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O nome do ficheiro está diferente do nome da classe e presumo que o queiras deixar todo em inglês?

sendEmbedToChannel(message: MessageEmbed, row: MessageActionRow, channelId: string): void;
}
2 changes: 2 additions & 0 deletions domain/service/channelResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ChannelSlug } from "../../types";
const fallbackChannelIds: Record<ChannelSlug, string> = {
[ChannelSlug.ENTRANCE]: "855861944930402344",
[ChannelSlug.JOBS]: "876826576749215744",
[ChannelSlug.QUESTION]: "1066328934825865216",
[ChannelSlug.MOD_CHANNEL]: "987719981443723266",
};

export default class ChannelResolver {
Expand Down
2 changes: 2 additions & 0 deletions domain/service/chatService.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export default interface ChatService {
sendMessageToChannel(message: string, channelId: string): void;
deleteMessageFromChannel(messageId: string, channelId: string): void;
sendDirectMessageToUser(message: string, userId: string): void;
}
3 changes: 2 additions & 1 deletion domain/service/commandUseCaseResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export default class CommandUseCaseResolver {
"!ja": async () =>
new SendMessageToChannelUseCase(deps).execute({
channelId: context.channelId,
message: ":point_right: https://dontasktoask.com/pt-pt/",
message:
":point_right: https://dontasktoask.com/pt-pt/",
}),
"!oc": async () =>
new SendMessageToChannelUseCase(deps).execute({
Expand Down
66 changes: 63 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { GuildMember, Message, Client, Intents } from "discord.js";
import { GuildMember, Message, Client, Intents, MessageEmbed } from "discord.js";
import * as dotenv from "dotenv";
import { ChannelSlug } from "./types";
import SendWelcomeMessageUseCase from "./application/usecases/sendWelcomeMessageUseCase";
import FileMessageRepository from "./infrastructure/repository/fileMessageRepository";
import ChatService from "./domain/service/chatService";
import DiscordEmbedService from "./infrastructure/service/discordEmbedService";
import QuestionChatService from "./application/usecases/sendMessageToChannel/sendPerguntaToChannel";
import DiscordChatService from "./infrastructure/service/discordChatService";
import ConsoleLoggerService from "./infrastructure/service/consoleLoggerService";
import MessageRepository from "./domain/repository/messageRepository";
Expand All @@ -11,15 +14,23 @@ import CommandUseCaseResolver from "./domain/service/commandUseCaseResolver";
import ChannelResolver from "./domain/service/channelResolver";
import KataService from "./domain/service/kataService/kataService";
import CodewarsKataService from "./infrastructure/service/codewarsKataService";
import DirectMessage from "./application/usecases/readDirectMessage";

dotenv.config();

const { DISCORD_TOKEN } = process.env;

const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILD_MESSAGES],
partials: ["CHANNEL"],
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.DIRECT_MESSAGES,
Intents.FLAGS.DIRECT_MESSAGE_TYPING,
Intents.FLAGS.GUILD_MEMBERS,
Intents.FLAGS.GUILD_MESSAGES,
],
});

const questionChatService: QuestionChatService = new DiscordEmbedService(client);
const messageRepository: MessageRepository = new FileMessageRepository();
const chatService: ChatService = new DiscordChatService(client);
const loggerService: LoggerService = new ConsoleLoggerService();
Expand Down Expand Up @@ -61,3 +72,52 @@ client.on("messageCreate", (messages: Message) => {
loggerService.log(error);
}
});

client.on("message", async (message) => {
const directMessage = new DirectMessage(message, client, channelResolver, chatService, questionChatService);

if (await directMessage.isValid()) {
directMessage.approveMessage();
}
});

client.on("interactionCreate", async (interaction) => {
if (!interaction.isButton()) return;

const {
message: {
id: messageId,
embeds: [{ description: messageContent }],
},
channelId,
} = interaction;

const userName = interaction.member?.user.username;
if (!messageContent) return;
const messageApprovedEmbed = new MessageEmbed()
.setColor("#0099ff")
.setTitle("Pergunta Anónima")
.setDescription(messageContent)
.setFooter({ text: `Aprovado por ${userName}` });

switch (interaction.customId.slice(0, 3)) {
case "apr":
{
const sentence = `PERGUNTA ANÓNIMA:\n${messageContent}`;
chatService.sendMessageToChannel(sentence, channelResolver.getBySlug(ChannelSlug.QUESTION));
interaction.update({ components: [], embeds: [messageApprovedEmbed] });
chatService.sendDirectMessageToUser(interaction.customId.slice(3), "A tua mensagem foi aprovada.");
}
break;

case "rej":
chatService.deleteMessageFromChannel(messageId, channelId);
chatService.sendDirectMessageToUser(
interaction.customId.slice(3),
"A tua mensagem não foi aprovada.\nVerifica se está de acordo com as regras."
);
break;
default:
break;
}
});
20 changes: 19 additions & 1 deletion infrastructure/service/discordChatService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,25 @@ export default class DiscordChatService implements ChatService {
if (!channel.isText()) {
throw new Error(`Channel with id ${channelId} is not a text channel!`);
}

channel.send(message);
}

async deleteMessageFromChannel(messageId: string, channelId: string): Promise<void> {
const channel = await this.client.channels.fetch(channelId);

if (channel === null) {
throw new Error(`Channel with id ${channelId} not found!`);
}

if (!channel.isText()) {
throw new Error(`Channel with id ${channelId} is not a text channel!`);
}

channel.messages.delete(messageId);
}

async sendDirectMessageToUser(userId: string, message: string): Promise<void> {
const user = await this.client.users.fetch(userId);
await user.send(message);
}
}
19 changes: 19 additions & 0 deletions infrastructure/service/discordEmbedService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Client, MessageEmbed, MessageActionRow } from "discord.js";

export default class DiscordEmbedService {
constructor(private client: Client) {}

async sendEmbedToChannel(embed: MessageEmbed, row: MessageActionRow, channelId: string): Promise<void> {
const channel = await this.client.channels.fetch(channelId);

if (channel === null) {
throw new Error(`Channel with id ${channelId} not found!`);
}

if (!channel.isText()) {
throw new Error(`Channel with id ${channelId} is not a text channel!`);
}

channel.send({ embeds: [embed], components: [row] });
}
}
Loading