Update interaction message appending a new container

Hey! I'd like to know if it's possible to do an interaction.update and appending a new container without changing or removing the original one, I had some tries but I'm having some troubles because the original container has a file inside and the message also have an actionrow with buttons I was wondering if there's a good method to do that
34 Replies
d.js toolkit
d.js toolkit2mo ago
Inky
Inky2mo ago
Yea. You can access the old message components with interaction.message.components Prob shouldn’t directly mutate it tho
Miky88
Miky88OP2mo ago
alr what about the file? cause i got the file field which is causing some issues i guess
Inky
Inky2mo ago
Wdym?
Miky88
Miky88OP2mo ago
[
ContainerComponent {
data: { type: 17, spoiler: false, id: 1, accent_color: null },
components: [
[SectionComponent],
[SeparatorComponent],
[TextDisplayComponent],
[TextDisplayComponent],
[SeparatorComponent],
[TextDisplayComponent],
[FileComponent],
[TextDisplayComponent]
]
},
ActionRow {
data: { type: 1, id: 12 },
components: [ [ButtonComponent], [ButtonComponent], [ButtonComponent] ]
}
]
[
ContainerComponent {
data: { type: 17, spoiler: false, id: 1, accent_color: null },
components: [
[SectionComponent],
[SeparatorComponent],
[TextDisplayComponent],
[TextDisplayComponent],
[SeparatorComponent],
[TextDisplayComponent],
[FileComponent],
[TextDisplayComponent]
]
},
ActionRow {
data: { type: 1, id: 12 },
components: [ [ButtonComponent], [ButtonComponent], [ButtonComponent] ]
}
]
As you can see I have a FileComponent here and when I try update with let's say components: [...interaction.message.components[0], newContainer] I get data.components[0].components[6].file.url[UNFURLED_MEDIA_ITEM_MUST_USE_ATTACHMENT_PROTOCOL]: This UnfurledMediaItem does not support arbitrary external urls. You must use the "attachment://" reference system.
Inky
Inky2mo ago
Why are you expanding the first component?
Miky88
Miky88OP2mo ago
uh
Inky
Inky2mo ago
That should be an error tbh
Miky88
Miky88OP2mo ago
i should not?
Inky
Inky2mo ago
You wrote [ ...interaction.message.components[0], ?
Miky88
Miky88OP2mo ago
actually wait let me try I'm doing this now
const successContainer = new ContainerBuilder()
.addTextDisplayComponents(
new TextDisplayBuilder()
.setContent(`✅ something`)
);


const originalComponents = interaction.message.components;

interaction.update({
components: [originalComponents, successContainer],
flags: [MessageFlags.IsComponentsV2],
allowedMentions: {}
})
const successContainer = new ContainerBuilder()
.addTextDisplayComponents(
new TextDisplayBuilder()
.setContent(`✅ something`)
);


const originalComponents = interaction.message.components;

interaction.update({
components: [originalComponents, successContainer],
flags: [MessageFlags.IsComponentsV2],
allowedMentions: {}
})
and I'm getting data.components[0][MODEL_TYPE_CONVERT]: Expected an object/dictionary.
Inky
Inky2mo ago
Now you have [ components,
Miky88
Miky88OP2mo ago
ok i see what you mean so i should ...originalComponents
Inky
Inky2mo ago
Yea
Miky88
Miky88OP2mo ago
And I'm getting the file error data.components[0].components[6].file.url[UNFURLED_MEDIA_ITEM_MUST_USE_ATTACHMENT_PROTOCOL]: This UnfurledMediaItem does not support arbitrary external urls. You must use the attachment:// reference system. Should I pass the files[] again?
Inky
Inky2mo ago
It should be keeping its attachments Problem is that the url in the File component got replaced with the Discord cdn one Can you confirm by logging originalComponents[0].components[6].file?
Miky88
Miky88OP2mo ago
Yep
UnfurledMediaItem {
data: {
width: 0,
url: 'https://cdn.discordapp.com/attachments/1313550338124419169/1427183486120366131/filename.pdf?ex=68edefb2&is=68ec9e32&hm=14358a6c92615cc5834fd55ecb2ca4ad8083d290bf46e31e88057a92691c64a5&',
proxy_url: 'https://media.discordapp.net/attachments/1313550338124419169/1427183486120366131/filename.pdf?ex=68edefb2&is=68ec9e32&hm=14358a6c92615cc5834fd55ecb2ca4ad8083d290bf46e31e88057a92691c64a5&',
placeholder_version: null,
placeholder: null,
loading_state: 2,
id: '1427183486334144525',
height: 0,
flags: 0,
content_type: 'application/pdf',
content_scan_metadata: { version: 2, flags: 0 },
attachment_id: '1427183486120366131'
}
}
UnfurledMediaItem {
data: {
width: 0,
url: 'https://cdn.discordapp.com/attachments/1313550338124419169/1427183486120366131/filename.pdf?ex=68edefb2&is=68ec9e32&hm=14358a6c92615cc5834fd55ecb2ca4ad8083d290bf46e31e88057a92691c64a5&',
proxy_url: 'https://media.discordapp.net/attachments/1313550338124419169/1427183486120366131/filename.pdf?ex=68edefb2&is=68ec9e32&hm=14358a6c92615cc5834fd55ecb2ca4ad8083d290bf46e31e88057a92691c64a5&',
placeholder_version: null,
placeholder: null,
loading_state: 2,
id: '1427183486334144525',
height: 0,
flags: 0,
content_type: 'application/pdf',
content_scan_metadata: { version: 2, flags: 0 },
attachment_id: '1427183486120366131'
}
}
Inky
Inky2mo ago
Was the url originally attachment://filename.pdf?
Miky88
Miky88OP2mo ago
yes
Inky
Inky2mo ago
Good thing is that it kept its filename You would just have to iterate through each component just to fix it though, if you want it to work for every case
Miky88
Miky88OP2mo ago
wouldn't it break if i hardcode the url tho? cause now it has the expire stuff params
Inky
Inky2mo ago
You shouldn’t have reupload the files, it’s still on the message It’s just that Discord changed the urls to https when it provided the message You just need the filename to change the urls back to attachment://
Miky88
Miky88OP2mo ago
oh I see
Inky
Inky2mo ago
path.basename from the node:path module will help you extract the name
Miky88
Miky88OP2mo ago
const originalComponents = interaction.message.components;
originalComponents.forEach(comp => {
if (comp.data.type == ComponentType.Container) {
comp.components.forEach(subcomp => {
if (subcomp.data.type == ComponentType.File) {
console.log(subcomp.data);
subcomp.data.url = `attachment://${subcomp.data.name}`;
}
});
}
});

interaction.update({
components: [...originalComponents, successContainer],
flags: [MessageFlags.IsComponentsV2],
allowedMentions: {}
})
const originalComponents = interaction.message.components;
originalComponents.forEach(comp => {
if (comp.data.type == ComponentType.Container) {
comp.components.forEach(subcomp => {
if (subcomp.data.type == ComponentType.File) {
console.log(subcomp.data);
subcomp.data.url = `attachment://${subcomp.data.name}`;
}
});
}
});

interaction.update({
components: [...originalComponents, successContainer],
flags: [MessageFlags.IsComponentsV2],
allowedMentions: {}
})
Am I doing this wrong? The console log returns
{
type: 13,
spoiler: false,
size: 2504,
name: 'filename.pdf',
id: 10
}
{
type: 13,
spoiler: false,
size: 2504,
name: 'filename.pdf',
id: 10
}
But I'm still getting the same error as befor
Inky
Inky2mo ago
I don’t think FileComponents has a name prop
Miky88
Miky88OP2mo ago
Okay I was writing to the wrong object, Now I changed it to subcomp.file.url = "attachment://" but it's read only TypeError: Cannot set property url of #<UnfurledMediaItem> which has only a getter
Inky
Inky2mo ago
Oh right, you have to convert to builders first Just map and add in the createComponent call const builder = createComponentBuilder(comp.toJSON());
Miky88
Miky88OP2mo ago
wait you mean only for the file or
Inky
Inky2mo ago
I don’t think you can just convert the file to a builder Not sure tbh Misspelled the function name there
Miky88
Miky88OP2mo ago
originalComponents.forEach(comp => {
if (comp.data.type == ComponentType.Container) {
comp.components.forEach(subcomp => {
if (subcomp.data.type == ComponentType.File) {
// subcomp.file.url = `attachment://${subcomp.data.name}`;
const builder = createComponentBuilder(subcomp.toJSON());
builder.setURL(`attachment://${subcomp.data.name}`);
subcomp = builder;
}
});
}
});
originalComponents.forEach(comp => {
if (comp.data.type == ComponentType.Container) {
comp.components.forEach(subcomp => {
if (subcomp.data.type == ComponentType.File) {
// subcomp.file.url = `attachment://${subcomp.data.name}`;
const builder = createComponentBuilder(subcomp.toJSON());
builder.setURL(`attachment://${subcomp.data.name}`);
subcomp = builder;
}
});
}
});
Umm not sure i did that good, sill getting data.components[0].components[6].file.url[UNFURLED_MEDIA_ITEM_MUST_USE_ATTACHMENT_PROTOCOL]: This UnfurledMediaItem does not support arbitrary external urls. You must use the attachment:// reference system. So I'm not sure it's even modifying that tbh
Inky
Inky2mo ago
Yea, easier just to map everything map instead of the first forEach
Miky88
Miky88OP2mo ago
yeah actually im totally doing this wrong cause forEach wont let me to modify the original object just realized lol Alright, now it works 😄 Posting the working code for the posterity 🙂
const originalComponents = interaction.message.components.map(comp => {
if (comp.data.type == ComponentType.Container) {
const newComponents = comp.components.map(subcomp => {
if (subcomp.data.type == ComponentType.File) {
const builder = createComponentBuilder(subcomp.toJSON());
builder.setURL(`attachment://${subcomp.data.name}`);
return builder;
}
return subcomp;
});
comp.components = newComponents;
}
return comp;
});
const originalComponents = interaction.message.components.map(comp => {
if (comp.data.type == ComponentType.Container) {
const newComponents = comp.components.map(subcomp => {
if (subcomp.data.type == ComponentType.File) {
const builder = createComponentBuilder(subcomp.toJSON());
builder.setURL(`attachment://${subcomp.data.name}`);
return builder;
}
return subcomp;
});
comp.components = newComponents;
}
return comp;
});
Thank you so much Chewinky!
Inky
Inky2mo ago
You don’t need to do it for the File component btw Oh nvm, I see how you did it You replaced the entire components of Container

Did you find this page helpful?