首先,我认为您可以使用嵌入来做到这一点,但由于 Discord 只显示三列,所以这一列没有按预期工作。我只是把它留在这里,因为如果有人最多只有三列,它就可以正常工作。
client.on('message', async (message) => {
if (message.author.bot) return;
const res = await fetch('https://pokemonrevolution.net/spawns/land_spawns.json');
const data = await res.json();
const filteredData = data.filter((p) => p.Pokemon === 'Pikachu');
const embed = new MessageEmbed().setTitle('Pokemons');
const obj = { map: '', area: '', tier: '', levels: '', ms: '', item: '' };
filteredData.forEach((spawn) => {
obj.map += `\n${spawn.Map}`;
obj.area += `\nLand`;
obj.tier += `\n${spawn.Tier}`;
obj.levels += `\n${spawn.MinLVL}-${spawn.MaxLVL}`;
obj.ms += `\n${spawn.MemberOnly ? 'Yes' : 'No'}`;
obj.item += `\n${spawn.Item ? spawn.Item : '-'}`;
});
embed.addFields(
{ name: '#Map', value: obj.map, inline: true },
{ name: 'Area', value: obj.area, inline: true },
{ name: 'Tier', value: obj.tier, inline: true },
{ name: 'Levels', value: obj.levels, inline: true },
{ name: 'MS', value: obj.ms, inline: true },
{ name: 'Item', value: obj.item, inline: true },
);
message.channel.send(embed);
});
结果如下所示:
Endothermic_Dragon 的解决方案有点接近你想要的,所以我做了他们的改进版本。您可以在下面找到它:
client.on('message', async (message) => {
if (message.author.bot) return;
const res = await fetch('https://pokemonrevolution.net/spawns/land_spawns.json');
const data = await res.json();
const filteredData = data.filter((p) => p.Pokemon === 'Pikachu');
// number of empty characters between columns
const padding = 3;
const lengths = filteredData.reduce(
(acc, curr) => {
const level = `${curr.MinLVL}-${curr.MaxLVL}`;
const tier = curr.Tier.toString();
return {
levels: level.length > acc.levels ? level.length : acc.levels,
map: curr.Map.length > acc.map ? curr.Map.length : acc.map,
memberOnly: curr.memberOnly ? 'Yes'.length : 'No'.length,
tier: tier.length > acc.tier ? tier.length : acc.tier,
};
},
{
levels: 0,
map: 0,
memberOnly: 0,
tier: 0,
},
);
const header = [
'#Map'.padEnd(lengths.map + padding),
'Area'.padEnd('Area'.length + padding),
'Rarity'.padEnd(lengths.tier + 'Tier '.length + padding),
'Levels'.padEnd(lengths.levels + padding),
'Members Only'.padEnd('Members Only'.length + padding),
'Item',
].join('');
const table = filteredData.map((d) => [
d.Map.padEnd(lengths.map + padding),
'Land'.padEnd('Land'.length + padding),
`Tier ${`${d.Tier}`.padEnd(lengths.tier + padding)}`,
`${d.MinLVL}-${d.MaxLVL}`.padEnd(lengths.levels + padding),
`${d.MemberOnly ? 'Yes' : 'No'}`.padEnd('Members Only'.length + padding),
d.Item ? d.Item : '-',
].join(''))
.join('\n');
message.channel.send(`\`\`\`md\n${header}\n${table}\`\`\``);
});
它似乎按预期工作:
如果您想在第一个端点没有结果的情况下从另一个端点获取,您可以使用以下代码。我还做了一些其他更改并尝试添加 cmets:
function getDaytimeNames(daytime = []) {
let names = ['M', 'D', 'N'];
return daytime
.reduce((acc, curr, i) => (curr ? [...acc, names[i]] : acc), [])
.join('/');
}
async function fetchData(pokemon) {
let res = await fetch('https://pokemonrevolution.net/spawns/land_spawns.json');
let data = await res.json();
let reducer = (area) => (acc, curr) => curr.Pokemon.toLowerCase() !== pokemon.toLowerCase()
? acc
: [
...acc,
{
area,
daytime: getDaytimeNames(curr.Daytime),
item: curr.Item ? curr.Item : '-',
levels: `${curr.MinLVL}-${curr.MaxLVL}`,
map: curr.Map,
memberOnly: `${curr.MemberOnly ? 'Yes' : 'No'}`,
tier: `Tier ${curr.Tier}`,
},
];
let landReducer = reducer('Land');
let filteredData = data.reduce(landReducer, []);
if (filteredData.length > 0)
return filteredData;
let surfReducer = reducer('Surf');
// If there was no filtered data from land_spawns, try surf_spawns
res = await fetch('https://pokemonrevolution.net/spawns/surf_spawns.json');
data = await res.json();
filteredData = data.reduce(surfReducer, []);
return filteredData;
}
function createTable(data, padding) {
const addPadding = (str, length) => str.padEnd((length || str.length) + padding);
const getMaxLengths = (acc, curr) => {
const getLongest = (prop) => curr[prop].length > acc[prop] ? curr[prop].length : acc[prop];
return {
area: getLongest('area'),
daytime: getLongest('daytime'),
levels: getLongest('levels'),
map: getLongest('map'),
memberOnly: getLongest('memberOnly'),
tier: getLongest('tier'),
};
};
const lengths = data.reduce(getMaxLengths, {
area: 0,
daytime: 0,
levels: 0,
map: 0,
memberOnly: 0,
tier: 0,
});
const headers = [
addPadding('#Map', lengths.map),
addPadding('Area', lengths.area),
addPadding('Daytime'),
addPadding('Rarity', lengths.tier),
addPadding('Levels', lengths.levels),
addPadding('Members Only'),
// No padding needed as it's the last column
'Item',
].join('');
const createRow = (d) => [
addPadding(d.map, lengths.map),
addPadding(d.area, lengths.area),
addPadding(d.daytime, 'Daytime'.length),
addPadding(d.tier, lengths.tier),
addPadding(d.levels, lengths.levels),
addPadding(d.memberOnly, 'Members Only'.length),
d.item,
].join('');
const table = data.map(createRow).join('\n');
return `${headers}\n${table}`;
}
// Create an array of rows with a max length
// making sure it always has complete rows only
function chunkify(str, max) {
let chunks = [];
while (str.length > max) {
let i = str.substr(0, max).lastIndexOf('\n');
chunks.push(str.substr(0, i));
str = str.substr(i + 1, str.length);
}
if (str.length > 0) {
chunks.push(str);
}
return chunks;
}
client.on('message', async (message) => {
if (message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
const pokemon = args[0];
const data = await fetchData(pokemon);
// Number of empty characters between columns
const padding = 2;
// Discord only allows a maximum of 2000 characters for content
const maxLength = 1980;
const table = createTable(data, padding);
chunkify(table, maxLength)
.forEach((chunk) => message.channel.send(`\`\`\`md\n${chunk}\`\`\``));
});