I want to make a feature where my bot... - Excludes the # from Category and VC Channels - Sort the channel by their numeral position and not by alphabetical order
The problem is I don't know how to split a # from a channel based off of their type. Also I can't figure out a way to sort the channels by position number.
I've tried this
.addField("Server's channels", serv.channels.calculatedPosition.map(c =>
${c}).join(' | '),true)
.addField("Server's channels", serv.channels.map(c =>
${c}).position.join(' | '),true)
var serv = message.guild
var myInfo = new discord.RichEmbed()
.setAuthor(`${serv.name}'s channels`,`${message.guild.iconURL}`)
.addField(`Server's channels`, serv.channels.map(c => `${c}`).join(' | '),true)
.setColor(0xffd000)
.setFooter('Server Roles.')
.setThumbnail(`${message.guild.iconURL}`)
message.channel.sendEmbed(myInfo);
Expect: discord.js-commando command that splits # from channels that are not a text and maps the channels by position. Actual: Bot maps channels by alphabetical order.
Sorting
The issue with GuildChannel.position
and GuildChannel.calculatedPosition
is that the position returned is based on the type of the channel. For instance, all the categories are ordered and given a number separately from text channels, and text channels separately from voice channels.
To combat this, we can make our own system which will use this to our advantage. We start by sorting and adding all the categories into a Collection paired with a sorted Collection of their children. Then, we iterate through and add the channels to the list.
Formatting
Technically, the #
symbol should be in front of non-text channels, since Discord converts their mentions to use it. However, it doesn't look very appealing and the logic seems to be a bit flawed.
All we have to do is use the name of the channel rather than its mention if it's not a text channel.
The Code
You may have to change a few variables around, and implement your embed as you wish. This is just an example.
const guild = message.guild;
// Comparison function which sorts channels according to appearance within Discord. Name
// is short for 'descending position,' but it also accomodates for voice channel location.
const descPos = (a, b) => {
if (a.type !== b.type) {
if (a.type === 'voice') return 1;
else return -1;
} else return a.position - b.position;
};
// Create a new Collection to hold categories and their children.
const channels = new Discord.Collection();
// Non-category channels without parent categories will appear at the top.
channels.set('__none', guild.channels.filter(channel => !channel.parent && channel.type !== 'category').sort(descPos));
// Add all the categories in order, mapped by their bolded name, into the Collection.
const categories = guild.channels.filter(channel => channel.type === 'category').sort(descPos);
categories.forEach(category => channels.set(category.id, category.children.sort(descPos)));
const list = [];
// Iterate through the categories and the corresponding Collection of their channels.
for (let [categoryID, children] of channels) {
// Retrieve the category from it's ID.
const category = guild.channels.get(categoryID);
// Push the category name (bolded for readability) into the list.
if (category) list.push(`**${category.name}**`);
// Iterate through the Collection of children. Push the mention for text, name for others.
for (let [, child] of children) list.push(child.type === 'text' ? child : child.name);
// To answer your comment about adding the emoji for voice channels...
// list.push(child.type === 'text' ? child : `🔊 ${child.name}`);
}
// Send the list of channels, appearing exactly how it does on the side. Make sure the
// joined list isn't too long for a message or embed field first to avoid an error.
message.channel.send(list.join('\n'))
.catch(console.error);
Resources
Discord.js Documentation: