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
57 changes: 57 additions & 0 deletions application/usecases/readDirectMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Message, Client, MessageEmbed, MessageActionRow, MessageButton } from "discord.js";
import sendDM from "../../application/usecases/sendMessageToChannel/sendDM";
import ChatService from "../usecases/sendMessageToChannel/sendPerguntaToChannel";
import DiscordChatService from "../../infrastructure/service/discordEmbedService";
import * as _ from "lodash";

class DirectMessage {
Copy link
Member

Choose a reason for hiding this comment

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

Por norma temos declarado as classes com o mesmo nome do ficheiro e com o sufixo UseCase. Consegues alterar?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

feito

Copy link
Contributor Author

Choose a reason for hiding this comment

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

feito

constructor(private message: Message, private client: Client) {}

async validate() {
Copy link
Member

Choose a reason for hiding this comment

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

Tendo em conta que a função validate retorna um bool e não um void, sugiro um isValid, penso fazer mais sentido.

E assim o teu if poderia ser um if (await isValid()) {.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

feito

const chatService: ChatService = new DiscordChatService(this.client);

if (this.message.author.id == this.client.user?.id) {
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 <= 1500
) {
return true;
} else {
sendDM(this.client, this.message.author.id, "Por favor usa o seguinte formato:\n!pergunta <mensagem>");
return false;
}
}
async messageApprove() {
Copy link
Member

Choose a reason for hiding this comment

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

Trocaria talvez o verbo para ficar em primeiro? Isto porque lemos "aprovar mensagem" e não "mensagem aprovar" 😅 que achas?

Suggested change
async messageApprove() {
async approveMessage(): void {

const chatService: ChatService = new DiscordChatService(this.client);
const modChannel = "987719981443723266";
zorkpt marked this conversation as resolved.
Show resolved Hide resolved
const sentence = this.message.content.split(" ").slice(1).join(" ");
const userName = this.message.author.username;

const row = new MessageActionRow().addComponents(
// BT Aceitar
new MessageButton().setLabel("Aprovar").setStyle("SUCCESS").setCustomId("bt1"),

// BT Eliminar
new MessageButton().setCustomId("bt2").setLabel("Eliminar").setStyle("DANGER")
zorkpt marked this conversation as resolved.
Show resolved Hide resolved
);

// Mensagem formato embed
const Mensagem = new MessageEmbed().setColor("#0099ff").setTitle("Pergunta Anónima").setDescription(sentence);
zorkpt marked this conversation as resolved.
Show resolved Hide resolved

// Passa como parametros mensagem(embed), row(2 butoes), e string com id do canal
await chatService.sendEmbedToChannel(Mensagem, row, modChannel);
const dmSent = sendDM(
this.client,
this.message.author.id,
"A tua pergunta foi colocada com sucesso.\nApós aprovação poderás visualizar no #canal."
);
if (!dmSent) console.log("dm não enviada");
}
}

export default DirectMessage;
20 changes: 20 additions & 0 deletions application/usecases/sendMessageToChannel/sendDM.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Client } from "discord.js";

function sendMessage(client: Client, userId: string, message: string): Boolean {
client.users.fetch(userId)
.then(async (user) => {
const exists = await user.send(message);
const res=!!exists
return res
})
.catch(e=>{
console.log(e);
return false
});
return false;

}



export default sendMessage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
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 {
sendEmbedToChannel(message: MessageEmbed, row: MessageActionRow, channelId: string): void;
}


1 change: 1 addition & 0 deletions domain/service/channelResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ChannelSlug } from "../../types";
const fallbackChannelIds: Record<ChannelSlug, string> = {
[ChannelSlug.ENTRANCE]: "855861944930402344",
[ChannelSlug.JOBS]: "876826576749215744",
[ChannelSlug.QUESTION]: "876826576749215744",
};

export default class ChannelResolver {
Expand Down
1 change: 1 addition & 0 deletions domain/service/chatService.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export default interface ChatService {
sendMessageToChannel(message: string, channelId: string): void;
deleteMessageFromChannel(messageId:string, channelId:string): void;
}
57 changes: 55 additions & 2 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GuildMember, Message, Client, Intents } from "discord.js";
import { GuildMember, Message, Client, Intents, MessageEmbed } from "discord.js";
import * as dotenv from "dotenv";
import SendWelcomeMessageUseCase from "./application/usecases/sendWelcomeMessageUseCase";
import FileMessageRepository from "./infrastructure/repository/fileMessageRepository";
Expand All @@ -11,15 +11,26 @@ 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";
import { channel } from "diagnostics_channel";
import { any } from "vitest-mock-extended";

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 canalPerguntaAnonima = "1066328934825865216";
zorkpt marked this conversation as resolved.
Show resolved Hide resolved
const messageRepository: MessageRepository = new FileMessageRepository();
const chatService: ChatService = new DiscordChatService(client);
const loggerService: LoggerService = new ConsoleLoggerService();
Expand Down Expand Up @@ -61,3 +72,45 @@ client.on("messageCreate", (messages: Message) => {
loggerService.log(error);
}
});

client.on("message", async (message) => {
const directMessage = new DirectMessage(message, client);
const validationCheck = await directMessage.validate();

validationCheck && directMessage.messageApprove();
});

client.on("interactionCreate", async (interaction) => {
if (!interaction.isButton()) return;
const messageId = interaction.message.id;
const channelId = interaction.channelId;
const userName = interaction.member?.user.username;
const anonChannel = client.channels.cache.get(channelId);

const messageContent = interaction.message.embeds[0].description;
if (!messageContent) return;
const messageApprovedEmbed = new MessageEmbed()
.setColor("#0099ff")
.setTitle("Pergunta Anónima")
.setDescription(messageContent)
.setFooter({ text: `Aprovado por ${userName}` });

switch (interaction.customId) {
case "bt1":
Copy link
Member

Choose a reason for hiding this comment

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

Este Ids deveriam ser algo mais específico caso queiramos vir a adicionar novos botões mais tarde.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

feito

{
const sentence = "PERGUNTA ANÓNIMA:\n" + messageContent;
chatService.sendMessageToChannel(sentence, canalPerguntaAnonima);
interaction.update({ components: [], embeds: [messageApprovedEmbed] });
}
break;

case "bt2":
{
chatService.deleteMessageFromChannel(messageId, channelId);
}
break;
default: {
console.log("default");
}
Copy link
Member

Choose a reason for hiding this comment

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

Presumo que possamos retirar isto daqui?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

não retirei porque senão não passa no lint, dá para desativar esse check ?

}
});
18 changes: 16 additions & 2 deletions infrastructure/service/discordChatService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Client } from "discord.js";
import { Client, MessageEmbed } from "discord.js";
import ChatService from "../../domain/service/chatService";

export default class DiscordChatService implements ChatService {
Expand All @@ -14,7 +14,21 @@ 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)
}
}
18 changes: 18 additions & 0 deletions infrastructure/service/discordDmService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import DmService from '../../domain/service/dmService'
import { Client } from "discord.js";

class DiscordDmService implements DmService {
private client: Client;

constructor(client: Client) {
this.client = client;
}

sendMessage(userId: string, message: string): void {
this.client.users.fetch(userId)
.then(user => user.send(message))
.catch(console.error);
}
}

export default DiscordDmService
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