Skip to content

Commit

Permalink
fix(network): fix image urls showing in embed
Browse files Browse the repository at this point in the history
content
  • Loading branch information
dev-737 committed Nov 25, 2023
1 parent 11a9797 commit 60e439f
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/InterChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class InterChat extends SuperClient {
public constructor() {
super();

this.on('ready', () => {
this.once('ready', () => {
// initialize the client
this.init();

Expand Down
60 changes: 48 additions & 12 deletions src/commands/context-menu/editMsg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ export default class DeleteMessage extends BaseCommand {
.setCustomId('newMessage')
.setStyle(TextInputStyle.Paragraph)
.setLabel('Please enter your new message.')
.setValue(`${target.content || target.embeds[0]?.description}`)
.setValue(
`${(target.content || target.embeds[0]?.description) ?? ''}\n${
target.embeds[0]?.image?.url || ''
}`,
)
.setMaxLength(950),
),
);
Expand Down Expand Up @@ -98,38 +102,63 @@ export default class DeleteMessage extends BaseCommand {
const userInput = interaction.fields.getTextInputValue('newMessage');
const hubSettings = new HubSettingsBitField(messageInDb.hub.settings);
const newMessage = hubSettings.has('HideLinks') ? replaceLinks(userInput) : userInput;
const censoredNewMessage = censor(newMessage);
const networkManager = interaction.client.getNetworkManager();

if (
newMessage.includes('discord.gg') ||
newMessage.includes('discord.com/invite') ||
newMessage.includes('dsc.gg')
hubSettings.has('BlockInvites') &&
(newMessage.includes('discord.gg') ||
newMessage.includes('discord.com/invite') ||
newMessage.includes('dsc.gg'))
) {
await interaction.editReply(
`${emojis.no} Do not advertise or promote servers in the network. Set an invite in \`/connection\` instead!`,
);
return;
}

// get image from embed
// get image from content
const oldImageUrl = target.content
? await networkManager.getAttachmentURL(target.content)
: target.embeds[0]?.image?.url;
const newImageUrl = await networkManager.getAttachmentURL(newMessage);
const guild = await interaction.client.fetchGuild(messageInDb.serverId);
const embedContent = newMessage.replace(oldImageUrl ?? '', '').replace(newImageUrl ?? '', '');

// if the message being edited is in compact mode
// then we create a new embed with the new message and old reply
// else we just use the old embed and replace the description
const newEmbed = target.content
? new EmbedBuilder()
.setAuthor({ name: target.author.username, iconURL: target.author.displayAvatarURL() })
.setDescription(newMessage)
.setDescription(embedContent || null)
.setColor(target.member?.displayHexColor ?? 'Random')
.setImage(newImageUrl || oldImageUrl || null)
.addFields(
target.embeds[0]
? [{ name: 'Reply-to', value: `${target.embeds[0].description}` }]
target.embeds[0].fields[0]
? [{ name: 'Replying-to', value: `${target.embeds[0].description}` }]
: [],
)
.setFooter({ text: `Server: ${guild?.name}` })
: EmbedBuilder.from(target.embeds[0]).setDescription(newMessage);
: EmbedBuilder.from(target.embeds[0])
.setDescription(embedContent || null)
.setImage(newImageUrl || oldImageUrl || null);

const censoredEmbed = EmbedBuilder.from(newEmbed).setDescription(censoredNewMessage);
const censoredEmbed = EmbedBuilder.from(newEmbed).setDescription(
censor(newEmbed.data.description ?? '') || null,
);
let compactMsg = newMessage;

if (oldImageUrl) {
if (newImageUrl) {
compactMsg = compactMsg.replace(oldImageUrl, newImageUrl);
}
else if (!newMessage.includes(oldImageUrl)) {
newEmbed.setImage(null);
censoredEmbed.setImage(null);
}
}

const censoredCmpctMsg = censor(compactMsg);

// find all the messages through the network
const channelSettingsArr = await db.connectedList.findMany({
Expand All @@ -141,13 +170,20 @@ export default class DeleteMessage extends BaseCommand {
if (!channelSettings) return false;

const webhookURL = channelSettings.webhookURL.split('/');
const webhook = await interaction.client.fetchWebhook(webhookURL[webhookURL.length - 2])?.catch(() => null);
const webhook = await interaction.client
.fetchWebhook(webhookURL[webhookURL.length - 2])
?.catch(() => null);

if (!webhook || webhook.owner?.id !== interaction.client.user.id) return false;

// finally, edit the message
return await webhook
.editMessage(element.messageId, {
content: channelSettings.compact
? channelSettings.profFilter
? censoredCmpctMsg
: compactMsg
: undefined,
threadId: channelSettings.parentId ? channelSettings.channelId : undefined,
embeds: !channelSettings.compact
? [channelSettings.profFilter ? censoredEmbed : newEmbed]
Expand Down
6 changes: 3 additions & 3 deletions src/commands/slash/Main/hub/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,10 @@ export default class Hub extends BaseCommand {
static readonly subcommands = new Collection<string, BaseCommand>();

async execute(interaction: ChatInputCommandInteraction): Promise<unknown> {
const subCommand =
const apiSubcommandName =
interaction.options.getSubcommandGroup() || interaction.options.getSubcommand();
const isValid = Hub.subcommands?.get(subCommand);
if (isValid) return await isValid.execute(interaction);
const subcommand = Hub.subcommands?.get(apiSubcommandName);
if (subcommand) return await subcommand.execute(interaction);
}

async autocomplete(interaction: AutocompleteInteraction): Promise<unknown> {
Expand Down
54 changes: 33 additions & 21 deletions src/managers/NetworkManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@ export default class NetworkManager extends Factory {
if (!checksPassed) return;

const allConnections = await this.fetchHubNetworks({ hubId: isNetworkMessage.hubId });

message.censoredContent = censor(message.content);

const attachment = message.attachments.first();
const attachmentURL = attachment ? attachment.url : await this.getAttachmentURL(message);
const attachmentURL = attachment
? attachment.url
: await this.getAttachmentURL(message.content);

if (attachmentURL) {
const reaction = await message.react(emojis.loading).catch(() => null);
Expand All @@ -87,7 +86,9 @@ export default class NetworkManager extends Factory {
stripIndents`
I have identified this image as NSFW (Not Safe For Work). Sharing NSFW content is against our network guidelines. Refrain from posting such content here.
**Detected NSFW:** ${predictions[0].className} ${Math.round(predictions[0].probability * 100)}%`,
**Detected NSFW:** ${predictions[0].className} ${Math.round(
predictions[0].probability * 100,
)}%`,
)
.setFooter({
text: 'Please be aware that AI predictions can be inaccurate at times, and we cannot guarantee perfect accuracy in all cases. 😔',
Expand All @@ -104,6 +105,8 @@ export default class NetworkManager extends Factory {
message.react('🔗').catch(() => null);
}

message.censoredContent = censor(message.content);

// fetch the referred message (message being replied to) from discord
const referredMessage = message.reference ? await message.fetchReference() : undefined;
// check if it was sent in the network
Expand All @@ -116,13 +119,14 @@ export default class NetworkManager extends Factory {
let referredContent: string | undefined = undefined;
let referredAuthor: User | null = null;

// only assign to this variable if one of these two conditions are true, not always
if (referredMessage) {
referredContent = await this.getReferredContent(referredMessage);

if (referredMessage?.author.id === message.client.user.id) {
referredContent = await this.getReferredContent(referredMessage);
referredAuthor = message.client.user;
}
else if (referenceInDb) {
referredContent = await this.getReferredContent(referredMessage);
referredAuthor = await message.client.users.fetch(referenceInDb.authorId).catch(() => null);
}
}
Expand All @@ -131,7 +135,7 @@ export default class NetworkManager extends Factory {
const { embed, censoredEmbed } = this.buildNetworkEmbed(message, {
attachmentURL,
referredContent,
embedCol: (isNetworkMessage.embedColor as `#${string}`) ?? undefined,
embedCol: (isNetworkMessage.embedColor as HexColorString) ?? undefined,
useNicknames: settings.has('UseNicknames'),
});

Expand All @@ -144,7 +148,7 @@ export default class NetworkManager extends Factory {
const reply = referenceInDb?.channelAndMessageIds.find(
(msg) => msg.channelId === connection.channelId,
);
// create a jump button to reply button
// create a jump to reply button
const jumpButton =
reply && referredMessage?.author
? new ActionRowBuilder<ButtonBuilder>().addComponents(
Expand Down Expand Up @@ -416,14 +420,12 @@ export default class NetworkManager extends Factory {
* @param message The message to search for an attachment URL.
* @returns The URL of the attachment, or null if no attachment is found.
*/
public async getAttachmentURL(message: Message) {
public async getAttachmentURL(string: string) {
// Tenor Gifs / Image URLs
const URLMatch = message.content.match(REGEX.IMAGE_URL);

const URLMatch = string.match(REGEX.IMAGE_URL);
if (URLMatch) return URLMatch[0];

const tenorRegex = /https:\/\/tenor\.com\/view\/.*-(\d+)/;
const gifMatch = message.content.match(tenorRegex);
const gifMatch = string.match(REGEX.TENOR_LINKS);

if (gifMatch) {
if (!process.env.TENOR_KEY) throw new TypeError('Tenor API key not found in .env file.');
Expand Down Expand Up @@ -457,7 +459,7 @@ export default class NetworkManager extends Factory {
useNicknames?: boolean;
},
): { embed: EmbedBuilder; censoredEmbed: EmbedBuilder } {
const formattedContent = opts?.referredContent?.replaceAll('\n', '\n> ');
const formattedReply = opts?.referredContent?.replaceAll('\n', '\n> ');

const embed = new EmbedBuilder()
.setAuthor({
Expand All @@ -466,13 +468,18 @@ export default class NetworkManager extends Factory {
: message.author.username,
iconURL: message.author.displayAvatarURL(),
})
.setDescription(message.content || null)
.setDescription(
// remove tenor links and image urls from the content
(opts?.attachmentURL
? message.content.replace(REGEX.TENOR_LINKS, '').replace(opts?.attachmentURL, '')
: message.content) || null,
)
.addFields(
formattedContent
formattedReply
? [
{
name: 'Replying To:',
value: `> ${formattedContent}` ?? 'Unknown.',
value: `> ${formattedReply}` ?? 'Unknown.',
},
]
: [],
Expand All @@ -485,13 +492,18 @@ export default class NetworkManager extends Factory {
.setColor(opts?.embedCol ?? 'Random');

const censoredEmbed = EmbedBuilder.from(embed)
.setDescription(message.censoredContent || null)
.setDescription(
// remove tenor links and image urls from the content
(opts?.attachmentURL
? message.censoredContent.replace(REGEX.TENOR_LINKS, '').replace(opts?.attachmentURL, '')
: message.censoredContent) || null,
)
.setFields(
formattedContent
formattedReply
? [
{
name: 'Replying To:',
value: `> ${censor(formattedContent)}` ?? 'Unknown.',
value: `> ${censor(formattedReply)}` ?? 'Unknown.',
},
]
: [],
Expand Down
9 changes: 4 additions & 5 deletions src/utils/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const badwords = require('./JSON/profanity.json') as typeof badwordsType;

export const isDevBuild = process.env.NODE_ENV === 'development';

export const CLIENT_ID = isDevBuild ? '798748015435055134' : '769921109209907241';
export const CLIENT_ID = isDevBuild ? '1075667060241211423' : '769921109209907241';
export const SUPPORT_SERVER_ID = '770256165300338709';

export const emojis: typeof normal = emotes.normal;
Expand All @@ -22,11 +22,9 @@ export const badgeEmojis: typeof badge = emotes.badge;

// Regexp
export const REGEX = {
IMAGE_URL:
/(?:(?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)(?:\.jpg|\.jpeg|\.gif|\.png)/,
IMAGE_URL: /\bhttps?:\/\/\S+?\.(?:png|jpe?g|gif)(?:\?\S+)?\b/,
/** no animated images */
STATIC_IMAGE_URL:
/(?:(?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)(?:\.jpg|\.jpeg|\.png)/,
STATIC_IMAGE_URL: /\bhttps?:\/\/\S+?\.(?:png|jpe?g)(?:\?\S+)?\b/,
/** ignores giphy and tenor */
LINKS: /https?:\/\/(?!tenor\.com|giphy\.com)\S+/g,
/** matches imgur urls */
Expand All @@ -36,6 +34,7 @@ export const REGEX = {
PROFANITY: new RegExp(`\\b(${badwords.profanity.join('|')})\\b`, 'ig'),
/** matches slurs */
SLURS: new RegExp(`\\b(${badwords.slurs.join('|')})\\b`, 'ig'),
TENOR_LINKS: /https:\/\/tenor\.com\/view\/.*-(\d+)/,
};

export const StaffIds = ['597265261665714186', '442653948630007808', '689082827979227160'];
Expand Down

0 comments on commit 60e439f

Please sign in to comment.