简体   繁体   English

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

[英]Edit part of a Message Embed (Discord.JS)

I have a channel that contains 10 embedded messages (1 embed per message).我有一个包含 10 条嵌入消息的通道(每条消息嵌入 1 条)。 Each embed is a leaderboard for people's best lap times, by Track.每个嵌入都是 Track 提供的人们最佳单圈时间的排行榜。

The layout of each embed is每个嵌入的布局是

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

Assume for example the 3rd embed looks something like this:例如,假设第三个嵌入看起来像这样:

| | Track 3 Name轨道 3 名称

| | John 37 seconds约翰 37 秒

| | Chris 39 seconds克里斯 39 秒

| | Jeff 40 seconds杰夫 40 秒

Beyond simply editing the embed and sending all the information updated manually, how could I update just one particular slot?除了简单地编辑嵌入并发送手动更新的所有信息之外,我怎么能只更新一个特定的插槽? For example, say Clark comes in with a 38 second lap, how would I move Chris to 3rd, remove Jeff, and add Clark to 2nd so the embed looks as such例如,假设克拉克以 38 秒的成绩进入,我将如何将 Chris 移至第 3 位,移除 Jeff,并将克拉克添加至第 2 位,以便嵌入看起来如此

| | Track 3 Name轨道 3 名称

| | John 37 seconds约翰 37 秒

| | Clark 38 seconds克拉克 38 秒

| | Chris 39 seconds克里斯 39 秒

Without changing any other embeds in the channel不更改频道中的任何其他嵌入

You don't necessarily need to create an entirely new embed and input all of the information into it.您不一定需要创建一个全新的嵌入并将所有信息输入其中。 You could get the current embed from the message, and edit the specific fields you need to edit.您可以从消息中获取当前嵌入,并编辑您需要编辑的特定字段。 Here is an example that you could adapt to work with your system:以下是您可以适应与您的系统一起使用的示例:

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]});
}

I tested this editTrack method using one of my bots' eval commands:我使用我的机器人的 eval 命令之一测试了这个editTrack方法:

BEFORE -前 -
首先嵌入

AFTER -后 -
编辑嵌入

The original embed is successfully edited with the new information.原始嵌入已使用新信息成功编辑。 And it only required the Message object containing the embed, the new lap's user, and the new lap's time.并且它只需要包含嵌入的Message对象、新圈的用户和新圈的时间。


Edit based on OP's comment:根据 OP 的评论进行编辑

For the answer to work when editing the track embed with an existing user, who has a new lap time, a slight modification needs to be made.为了在编辑带有新单圈时间的现有用户嵌入的轨道时工作的答案,需要稍作修改。 Before removing the 4th field of the embed, you must do something like this:在删除嵌入的第 4 个字段之前,您必须执行以下操作:

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

Here's what that code is doing.这是该代码正在执行的操作。 First, we create a Set .首先,我们创建一个Set Sets are iterable structures similar to arrays, but they can only contain unique values.集合是类似于数组的可迭代结构,但它们只能包含唯一值。 We can therefore use sets to ensure there are no repeats of a user's name.因此,我们可以使用集合来确保没有重复的用户名。 Next, we filter the fields;接下来,我们过滤字段; only the fields whose user is not already contained in names will remain.只有用户尚未包含在names的字段才会保留。 If a user's name is not already in names , it gets added to the set via .add() .如果用户名尚未在names ,则会通过.add()将其添加到集合中。 And because the fields are already sorted with the quickest lap time coming first, only the quickest lap of a given user will remain;并且因为这些字段已经按照最快单圈时间进行排序,所以只会保留给定用户的最快单圈; any longer lap times by the same user will be filtered out.同一用户的任何更长的单圈时间将被过滤掉。

Note that I only tested this edit briefly, let me know if there are any logical errors or further issues caused by it (or if it fails to work entirely).请注意,我只是简单地测试了这个编辑,让我知道是否有任何逻辑错误或由它引起的其他问题(或者它是否完全无法正常工作)。

Thanks to Cannicide's helpful answer, it led me down the right track.感谢Cannicide 的有用回答,它让我走上了正轨。

To achieve the end result of sorting times and overwriting existing times, I ended up with the following function.为了实现排序时间和覆盖现有时间的最终结果,我最终使用了以下函数。 I require all times be submitted in the format: MINUTES:SECONDS (0:35 = 35s | 4:24 = 4m24s | 62:08 = 1h2m8s).我要求所有时间都以以下格式提交: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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM