Refactoring and bugfixes
This commit is contained in:
16
src/bot.ts
16
src/bot.ts
@@ -4,6 +4,8 @@ import { readyHandler } from "./functions/ready.ts";
|
|||||||
import feedMessagesArray from "./functions/feedMessagesArray.ts";
|
import feedMessagesArray from "./functions/feedMessagesArray.ts";
|
||||||
import handleMessageReposts from "./functions/handleMessageReposts.ts";
|
import handleMessageReposts from "./functions/handleMessageReposts.ts";
|
||||||
import deleteMessageFromMessagesArray from "./functions/deleteMessageFromMessagesArray.ts";
|
import deleteMessageFromMessagesArray from "./functions/deleteMessageFromMessagesArray.ts";
|
||||||
|
import handleMessageUpdate from "./functions/handleMessageUpdate.ts";
|
||||||
|
import deleteRepliesToAuthorMessage from "./functions/deleteRepliesToAuthorMessage.ts";
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
intents: [
|
intents: [
|
||||||
@@ -15,17 +17,31 @@ const client = new Client({
|
|||||||
|
|
||||||
let messagesArr: Message[];
|
let messagesArr: Message[];
|
||||||
|
|
||||||
|
let botIsReady = false;
|
||||||
|
|
||||||
client.once(Events.ClientReady, async (client) => {
|
client.once(Events.ClientReady, async (client) => {
|
||||||
readyHandler(client);
|
readyHandler(client);
|
||||||
messagesArr = await feedMessagesArray(client);
|
messagesArr = await feedMessagesArray(client);
|
||||||
|
botIsReady = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on(Events.MessageCreate, async (message) => {
|
client.on(Events.MessageCreate, async (message) => {
|
||||||
|
if (!botIsReady) return;
|
||||||
|
|
||||||
messagesArr = handleMessageReposts(messagesArr, message);
|
messagesArr = handleMessageReposts(messagesArr, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
client.on(Events.MessageUpdate, async (message) => {
|
||||||
|
if (!botIsReady) return;
|
||||||
|
|
||||||
|
messagesArr = handleMessageUpdate(messagesArr, message); // TODO
|
||||||
|
});
|
||||||
|
|
||||||
client.on(Events.MessageDelete, async (message) => {
|
client.on(Events.MessageDelete, async (message) => {
|
||||||
|
if (!botIsReady) return;
|
||||||
|
|
||||||
messagesArr = deleteMessageFromMessagesArray(messagesArr, message);
|
messagesArr = deleteMessageFromMessagesArray(messagesArr, message);
|
||||||
|
deleteRepliesToAuthorMessage(message); // TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
await client.login(process.env.DISCORD_TOKEN);
|
await client.login(process.env.DISCORD_TOKEN);
|
||||||
|
|||||||
@@ -1,33 +1,47 @@
|
|||||||
import { TextChannel, type Message } from "discord.js";
|
import { TextChannel, type Message } from "discord.js";
|
||||||
import { italic, underline } from "../utils/message.ts";
|
import { italic, underline } from "../utils/message.ts";
|
||||||
|
import orderMessagesArrayByPostDate from "./orderMessagesArrayByPostDate.ts";
|
||||||
|
|
||||||
export default function attemptReplyAuthorMessage(
|
export default function attemptReplyAuthorMessage(
|
||||||
authorMessage: Message,
|
authorMessage: Message,
|
||||||
url: string,
|
url: string,
|
||||||
originalMessages: Message[],
|
originalMessages: Message[],
|
||||||
): void {
|
): void {
|
||||||
if (!(authorMessage.channel instanceof TextChannel)) return;
|
if (!(authorMessage.channel instanceof TextChannel)) return;
|
||||||
if (!authorMessage.guild) return;
|
if (!authorMessage.guild) return;
|
||||||
|
|
||||||
let replyMessage = `Hey! [${underline("O link que voce mandou")}](<${url}>) ja foi mandado no passado! Voce eh um repostado!`;
|
let replyMessage = `Hey! [${underline("O link que voce mandou")}](<${url}>) ja foi mandado no passado! Voce eh um repostado!`;
|
||||||
|
|
||||||
for (let index = 0; index < originalMessages.length; index++) {
|
const sortedOriginalMessages = orderMessagesArrayByPostDate(originalMessages);
|
||||||
const msg = originalMessages[index];
|
|
||||||
if (!msg) return;
|
|
||||||
|
|
||||||
const { id, guildId, channelId, author } = msg;
|
for (let index = 0; index < sortedOriginalMessages.length; index++) {
|
||||||
|
const message = sortedOriginalMessages[index];
|
||||||
|
if (!message) return;
|
||||||
|
|
||||||
if (!author.globalName) return;
|
const { id, guildId, channelId, author } = message;
|
||||||
|
|
||||||
const messageUrl = `https://discord.com/channels/${guildId}/${channelId}/${id}`;
|
if (!author.globalName) return;
|
||||||
replyMessage += `\n- Mensagem original ${++index} (por ${italic(author.globalName)}): ${messageUrl}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
authorMessage
|
const authorName = `"${author.globalName}"`;
|
||||||
.reply({
|
|
||||||
content: replyMessage,
|
const msgNumber = index.toString().padStart(2, "0");
|
||||||
options: { ephemeral: true },
|
|
||||||
})
|
const messageUrl = `https://discord.com/channels/${guildId}/${channelId}/${id}`;
|
||||||
.then()
|
|
||||||
.catch((_) => null);
|
let messageTemplateStart = "Postador original";
|
||||||
|
|
||||||
|
if (index !== 0) {
|
||||||
|
messageTemplateStart = `Repost numero ${msgNumber}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
replyMessage += `\n- ${messageTemplateStart} (por ${italic(authorName)}): ${messageUrl}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
authorMessage
|
||||||
|
.reply({
|
||||||
|
content: replyMessage,
|
||||||
|
options: { ephemeral: true },
|
||||||
|
})
|
||||||
|
.then()
|
||||||
|
.catch((_) => null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import type { Message } from "discord.js";
|
|
||||||
import type MessageInfoWithReposts from "../interfaces/MessageInfoWithReposts.ts";
|
|
||||||
import { transformMessageArrayInMap } from "../utils/message.ts";
|
|
||||||
|
|
||||||
export default function checkMessagesArrayForReposts(
|
|
||||||
messagesArray: Message[],
|
|
||||||
): Map<string, MessageInfoWithReposts> {
|
|
||||||
const urlMessagesMap = transformMessageArrayInMap(messagesArray);
|
|
||||||
|
|
||||||
const messageInfoWithRepostsMap = new Map<string, MessageInfoWithReposts>();
|
|
||||||
|
|
||||||
for (const [url, messagesMentioningUrlArray] of urlMessagesMap) {
|
|
||||||
if (messagesMentioningUrlArray.length === 1) continue;
|
|
||||||
|
|
||||||
const originalMessage = messagesMentioningUrlArray.reduce((prev, curr) =>
|
|
||||||
prev.createdTimestamp < curr.createdTimestamp ? prev : curr,
|
|
||||||
);
|
|
||||||
|
|
||||||
const messageInfoWithRepostsMapPosition =
|
|
||||||
messageInfoWithRepostsMap.get(url);
|
|
||||||
|
|
||||||
if (!messageInfoWithRepostsMapPosition) {
|
|
||||||
messageInfoWithRepostsMap.set(url, {
|
|
||||||
originalMessage,
|
|
||||||
repetitions: messagesMentioningUrlArray.filter(
|
|
||||||
(elm) => elm !== originalMessage,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return messageInfoWithRepostsMap;
|
|
||||||
}
|
|
||||||
5
src/functions/deleteRepliesToAuthorMessage.ts
Normal file
5
src/functions/deleteRepliesToAuthorMessage.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { Message, PartialMessage } from "discord.js";
|
||||||
|
|
||||||
|
export default function deleteRepliesToAuthorMessage(
|
||||||
|
authorMessage: Message | PartialMessage,
|
||||||
|
): void { }
|
||||||
@@ -6,22 +6,24 @@ import updateMessagesArray from "./updateMessagesArray.ts";
|
|||||||
import attemptReplyAuthorMessage from "./attemptReplyAuthorMessage.ts";
|
import attemptReplyAuthorMessage from "./attemptReplyAuthorMessage.ts";
|
||||||
|
|
||||||
export default function handleMessageReposts(
|
export default function handleMessageReposts(
|
||||||
messagesArray: Message[],
|
messagesArray: Message[],
|
||||||
newMessage: Message,
|
newMessage: Message,
|
||||||
): Message[] {
|
): Message[] {
|
||||||
const urlMessagesMap = transformMessageArrayInMap(messagesArray);
|
const urlMessagesMap = transformMessageArrayInMap(messagesArray);
|
||||||
|
|
||||||
const newMessageClearedUrl = clearUrl(newMessage.content);
|
const newMessageClearedUrl = clearUrl(newMessage.content);
|
||||||
|
|
||||||
if (!newMessageClearedUrl) return messagesArray;
|
if (!newMessageClearedUrl) return messagesArray;
|
||||||
|
|
||||||
const originalMessages = urlMessagesMap.get(newMessageClearedUrl);
|
const originalMessages = urlMessagesMap.get(newMessageClearedUrl);
|
||||||
|
|
||||||
if (!originalMessages) {
|
const newMessagesArray = updateMessagesArray(messagesArray, newMessage);
|
||||||
return updateMessagesArray(messagesArray, newMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
attemptReplyAuthorMessage(newMessage, newMessageClearedUrl, originalMessages);
|
if (!originalMessages) {
|
||||||
|
return newMessagesArray;
|
||||||
|
}
|
||||||
|
|
||||||
return messagesArray;
|
attemptReplyAuthorMessage(newMessage, newMessageClearedUrl, originalMessages);
|
||||||
|
|
||||||
|
return newMessagesArray;
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/functions/handleMessageUpdate.ts
Normal file
8
src/functions/handleMessageUpdate.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { Message, PartialMessage } from "discord.js";
|
||||||
|
|
||||||
|
export default function handleMessageUpdate(
|
||||||
|
messagesArray: Message[],
|
||||||
|
updatedMessage: Message | PartialMessage,
|
||||||
|
): Message[] {
|
||||||
|
return messagesArray;
|
||||||
|
}
|
||||||
17
src/functions/orderMessagesArrayByPostDate.ts
Normal file
17
src/functions/orderMessagesArrayByPostDate.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { Message } from "discord.js";
|
||||||
|
|
||||||
|
function compareMessageByTimestamp(prevMessage: Message, currMessage: Message) {
|
||||||
|
if (prevMessage.createdTimestamp < currMessage.createdTimestamp) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (prevMessage.createdTimestamp > currMessage.createdTimestamp) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function orderMessagesArrayByPostDate(
|
||||||
|
messagesArray: Message[],
|
||||||
|
): Message[] {
|
||||||
|
return messagesArray.sort(compareMessageByTimestamp);
|
||||||
|
}
|
||||||
@@ -1,42 +1,71 @@
|
|||||||
|
type HostnameMap = {
|
||||||
|
[key: string]: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type DomainMap = {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HOSTNAME_MAPPINGS: HostnameMap = {
|
||||||
|
x: ["fixupx", "vxx"],
|
||||||
|
reddit: ["rxddit"],
|
||||||
|
bsky: ["bskye"],
|
||||||
|
};
|
||||||
|
|
||||||
|
const DOMAIN_ENDINGS: DomainMap = {
|
||||||
|
twitter: "x",
|
||||||
|
"vm.tiktok": "vm.tiktok",
|
||||||
|
tiktok: "tiktok",
|
||||||
|
instagram: "instagram",
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHostnameReplacement = (cleanHostname: string): string => {
|
||||||
|
// Check for exact matches first - now searching through values to find the key
|
||||||
|
const exactMatch = Object.entries(HOSTNAME_MAPPINGS).find(
|
||||||
|
([_, possibleNames]) => possibleNames.includes(cleanHostname),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (exactMatch) {
|
||||||
|
return exactMatch[0]; // Return the key (replacement value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check domain endings
|
||||||
|
return (
|
||||||
|
Object.entries(DOMAIN_ENDINGS).find(([ending]) =>
|
||||||
|
cleanHostname.endsWith(ending),
|
||||||
|
)?.[1] ?? ""
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export function clearUrl(url: string): string {
|
export function clearUrl(url: string): string {
|
||||||
const urlRegex = /(https?:\/\/[^ ]*)/;
|
const urlRegex = /(https?:\/\/[^ ]*)/;
|
||||||
|
|
||||||
const matchUrl = url.match(urlRegex);
|
const matchUrl = url.match(urlRegex);
|
||||||
|
|
||||||
if (!matchUrl) return "";
|
if (!matchUrl) return "";
|
||||||
if (!matchUrl[0]) return "";
|
if (!matchUrl[0]) return "";
|
||||||
|
|
||||||
let clearedUrl = matchUrl[0].split("?")[0];
|
let clearedUrl = matchUrl[0].split("?")[0];
|
||||||
|
|
||||||
if (!clearedUrl) return "";
|
if (!clearedUrl) return "";
|
||||||
|
|
||||||
clearedUrl = clearedUrl.split("\n")[0];
|
clearedUrl = clearedUrl.split("\n")[0];
|
||||||
|
|
||||||
if (!clearedUrl) return "";
|
if (!clearedUrl) return "";
|
||||||
|
|
||||||
clearedUrl = clearedUrl.replace(/\/+$/, "");
|
clearedUrl = clearedUrl.replace(/\/+$/, "");
|
||||||
|
|
||||||
const { hostname } = new URL(clearedUrl);
|
const { hostname } = new URL(clearedUrl);
|
||||||
const cleanHostname = hostname.substring(
|
const cleanHostname = hostname.substring(
|
||||||
hostname.indexOf(".") + 1,
|
hostname.indexOf(".") + 1,
|
||||||
hostname.lastIndexOf("."),
|
hostname.lastIndexOf("."),
|
||||||
);
|
);
|
||||||
|
|
||||||
let hostnameReplaceStr = "";
|
const hostnameReplaceStr = getHostnameReplacement(cleanHostname);
|
||||||
|
|
||||||
if (cleanHostname === "fixupx" || cleanHostname.endsWith("twitter")) {
|
if (hostnameReplaceStr) {
|
||||||
hostnameReplaceStr = "x";
|
clearedUrl = clearedUrl.replace(cleanHostname, hostnameReplaceStr);
|
||||||
} else if (cleanHostname.endsWith("vm.tiktok")) {
|
}
|
||||||
hostnameReplaceStr = "vm.tiktok";
|
|
||||||
} else if (cleanHostname.endsWith("tiktok")) {
|
|
||||||
hostnameReplaceStr = "tiktok";
|
|
||||||
} else if (cleanHostname.endsWith("instagram")) {
|
|
||||||
hostnameReplaceStr = "instagram";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostnameReplaceStr) {
|
return clearedUrl;
|
||||||
clearedUrl = clearedUrl.replace(cleanHostname, hostnameReplaceStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return clearedUrl;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user