Scripting Guide
Lesson 5: Channels, Threads, and the Server
Fetching and creating channels, editing channel settings, threads, invites, webhooks, and server-level management.
Getting hold of a channel
Channels come from three places: the payload (message.channel, or payload.channel on channel events), a lookup by ID with guild.channels.fetch(id), or the cached list guild.channels.list() which returns plain snapshots of every channel.
export async function onMessage(message) {
if (message.author.bot) return;
if (message.content !== "!channels") return;
// list() is synchronous data: id, name, type, parentId, topic, ...
const channels = message.guild.channels.list();
const text = channels
.filter((c) => c.type === 0) // 0 = GuildText (see ChannelType in Lesson 6)
.map((c) => "#" + c.name)
.join(", ");
await message.reply("Text channels: " + text);
}Creating and editing channels
export async function onMessage(message) {
if (message.author.bot) return;
if (message.content !== "!ticket") return;
const channel = await message.guild.channels.create({
name: "ticket-" + message.author.username,
type: 0, // text channel
topic: "Support ticket for " + message.author.username,
permissionOverwrites: [
// Hide from everyone...
{ id: message.guild.id, deny: ["ViewChannel"] },
// ...except the requester.
{ id: message.author.id, allow: ["ViewChannel", "SendMessages"] },
],
reason: "Ticket requested",
});
if (channel.error) {
await message.reply("Could not create the ticket: " + channel.error);
return;
}
await channel.send("Ticket opened. A moderator will be with you shortly.");
await message.reply("Created <#" + channel.id + ">");
}Existing channels expose setters that each return the updated channel snapshot: setName, setTopic, setNSFW, setRateLimitPerUser (slowmode seconds), setParent (move to a category), setPosition, setBitrate and setUserLimit (voice), plus clone(), delete(reason), and lockPermissions() to re-sync with the category.
Permission overwrites
Fine-grained access is managed through channel.permissionOverwrites: create(id, { ViewChannel: false }), edit(id, options), delete(id), and set([...]) to replace everything. The id is a role ID or a member ID; permission names are the same strings used in member.permissions.
Threads
export async function onMessage(message) {
if (message.author.bot) return;
if (message.content !== "!discuss") return;
// Start a thread from the triggering message...
const thread = await message.startThread({
name: "Discussion: " + message.content.slice(0, 50),
autoArchiveDuration: 1440, // minutes: 60, 1440, 4320, or 10080
});
if (thread.error) return;
// ...or create one on a channel: message.channel.threads.create({ name })
await thread.send("Keep the discussion in here, please.");
await thread.members.add(message.author.id);
}Thread objects support send, setName, setArchived, setLocked, setAutoArchiveDuration, join, leave, delete, member management via members.add/remove, and history via messages.fetch. A channel's active threads are listed with channel.threads.fetchActive().
Invites and webhooks
channel.createInvite({ maxAge, maxUses, temporary, unique, reason })returns invite data includingurl.channel.fetchInvites()lists the channel's invites with use counts.channel.createWebhook({ name, avatar? })returns a webhook you cansendthrough (useful for posting with a custom name/avatar);fetchWebhooks()lists them; webhooks supporteditMessage,deleteMessage,edit, anddelete.
Server-level management
guild.roles.create({ name, color, permissions }),guild.roles.fetch(id),guild.roles.list(); fetched roles exposesetName,setColor,setHoist,setMentionable,setPermissions,setPosition,edit, anddelete.guild.emojis.list() / create({ attachment, name }) / delete(id)and the same trio forguild.stickers.guild.setName(name)andguild.setIcon(url)change server identity (icon URLs must be public http(s)).guild.fetchOwner()returns the owner as a member object.guild.fetchAuditLogs({ limit, type, userId })returns up to 50 audit entries (Lesson 13 uses this).
Common pitfalls
- Channel types are numbers. Text is
0, voice is2, category is4, announcements5, forums15. ImportChannelTypefrom"discord"for readable names (Lesson 6). - Overwrites need IDs as strings. Pass role/member IDs, not names or mention strings.
- `autoArchiveDuration` only accepts 60, 1440, 4320, or 10080 (minutes).
- Creating channels in a loop. Channel creation is heavily rate limited by Discord; create one per run, not dozens.
Exercise
Build a !slowmode <seconds> command for users with ManageChannels that calls setRateLimitPerUser, confirms the new value, and replies with an error message when the action result has an error property (try it in a channel where the bot lacks permission).