编辑消息嵌入的一部分 (Discord.JS)

Edit part of a Message Embed (Discord.JS)

我有一个包含 10 条嵌入消息的频道(每条消息嵌入 1 条消息)。每个嵌入都是人们最好的单圈时间排行榜,由 Track 提供。

每个嵌入的布局是

const trackName = new MessageEmbed
.setTitle(trackName) 
.addField(user1, lapTime)
.addField(user2, lapTime) 
.addField(user3, lapTime)

假设第三个嵌入看起来像这样:

| 曲目 3 名称

|约翰 37 秒

|克里斯 39 秒

|杰夫 40 秒

除了简单地编辑嵌入并手动发送所有更新的信息之外,我如何才能只更新一个特定的广告位?例如,假设 Clark 跑了 38 秒,我如何将 Chris 移到第 3 位,移除 Jeff,并将 Clark 添加到第 2 位,这样嵌入看起来就这样

| 曲目 3 名称

|约翰 37 秒

|克拉克 38 秒

|克里斯 39 秒

不改变频道中的任何其他嵌入

您不一定需要创建一个全新的嵌入并将所有信息输入其中。您可以从消息中获取当前嵌入,并编辑您需要编辑的特定字段。这是一个您可以适应您的系统的示例:

function editTrack(msg, newUser, newTime) {
    //Assume `msg` is the message in the channel containing the embed you want to edit
    //currentEmbed is now the embed you want to edit
    let currentEmbed = msg.embeds[0];

    //Add `newUser` and its `newTime` to the embed as a new field, in the last position
    currentEmbed.addField(newUser, newTime);

    //Sorts the embed's fields by the lap times of each user, from lowest to highest
    //This example numerically sorts the fields by the number in their value
    //This does most of the work for you; the laps are now in the correct order
    currentEmbed.fields.sort((a, b) => Number(a.value.split(" second")[0]) - Number(b.value.split(" second")[0]));

    //If you want to display only the top 3, remove the 4th field of the embed (if any)
    if (currentEmbed.fields.length == 4) currentEmbed.fields.splice(3, 1);

    //Now, we need to edit the message with our updated embed (djs 13.x syntax)
    return msg.edit({embeds: [currentEmbed]});
}

我使用我的一个机器人的 eval 命令测试了这个 editTrack 方法:

之前-

之后 -

使用新信息成功编辑原始嵌入。它只需要包含嵌入、新圈的用户和新圈的时间的 Message 对象。


根据 OP 的评论编辑

为了在编辑轨道嵌入时与现有用户一起工作时的答案,他有一个新的单圈时间,需要进行轻微的修改。在删除嵌入的第 4 个字段之前,您必须执行如下操作:

const names = new Set();
currentEmbed.fields = currentEmbed.fields.filter(field =>
    !names.has(field.name) && names.add(field.name)
);

代码的作用如下。首先,我们创建一个 Set。集合是类似于数组的可迭代结构,但它们只能包含唯一值。因此,我们可以使用集合来确保没有重复的用户名。接下来,我们过滤字段;只有用户未包含在 names 中的字段才会保留。如果用户名不在 names 中,它会通过 .add() 添加到集合中。并且由于这些字段已经按照最快圈速排在第一位进行了排序,因此只会保留给定用户的最快圈速;同一用户的任何更长单圈时间将被过滤掉。

请注意,我只是简单地测试了这个编辑,如果有任何逻辑错误或由它引起的其他问题(或者如果它无法完全工作),请告诉我。

感谢 Cannicide's 有用的回答,它让我走上了正确的道路。

为了达到排序时间和覆盖现有时间的最终结果,我最终实现了以下功能。我要求所有时间都以以下格式提交:MINUTES:SECONDS (0:35 = 35s | 4:24 = 4m24s | 62:08 = 1h2m8s).

function editLb(theMessage, newUser, newTime) {
    //get the embed you want to edit
    let currentEmbed = theMessage.embeds[0];

    //Check all existing fields for the same newUser, if the same newUser
    //is found, replace that entire field with the name: "Placeholder"
    //and the value: "999:99". This will also remove any existing duplicates.
    currentEmbed.fields.forEach(field => {
        if (field.name == newUser) {
            field.name = `Placeholder`;
            field.value = `999:99`;
        }
    })

    //add the newUser and the newTime to a new field
    currentEmbed.addField(`${newUser}`, `${newTime}`);

    //sort all available fields effectively by seconds, by taking 
    // (minutes*60) + (seconds)
    currentEmbed.fields.sort((a, b) => Number((a.value.split(":")[0])*60 + (a.value.split(":")[1])) - Number((b.value.split(":")[0])*60 + (b.value.split(":")[1])));
    
    //If there are now 4 fields, remove the slowest(last) one.
    if (currentEmbed.fields.length == 4) currentEmbed.fields.splice(3, 1);
}