0

Create Discord thread and send messages

by
Published Mar 18, 2024

This script is designed to automate the process of creating a thread in a Discord channel and populating it with a series of messages using a Discord bot. It starts by validating the lengths of the thread name and all messages to ensure they comply with Discord's character limits. If validations pass, it proceeds to create the thread and then sequentially sends the first message, an array of messages, and a final message to the thread. The script handles errors and rate limiting by Discord's API, ensuring that messages are only sent if the thread creation is successful and retrying message sends if rate-limited. Needed bot permissions are: 'Create Private Threads' and 'Send Messages'

Script discord Verified

The script

Submitted by henri186 Bun
Verified 7 days ago
1
type DiscordBotConfiguration = {
2
  // Bot token, sent as `Authorization: Bot <token>`. Preferred field.
3
  bot_token?: string,
4
  // Ed25519 key for verifying interactions. Legacy: older resources stored the
5
  // bot token here, so we fall back to it for backward compatibility.
6
  public_key?: string,
7
  application_id: string
8
};
9

10
/**
11
 * Creates a thread in Discord and sends a series of messages to it using the Discord bot configuration.
12
 * The series starts with a firstMessage, followed by the messages array, and ends with a lastMessage.
13
 * Before attempting to create the thread, it validates that all messages (including first and last) are within the character limit.
14
 * If any message exceeds the limit, it throws an error without creating the thread.
15
 * @param discordBotConfigResource Contains the Discord bot configuration necessary for API requests.
16
 * @param channelId The ID of the Discord channel where the thread will be created.
17
 * @param threadName The name of the thread to be created. Must be 100 characters or less.
18
 * @param firstMessage The first message to be sent to the thread. Must be 2000 characters or less.
19
 * @param messages An array of messages to be sent to the thread after the firstMessage and before the lastMessage. Each message must be 2000 characters or less.
20
 * @param lastMessage The last message to be sent to the thread. Must be 2000 characters or less.
21
 * @returns An object indicating the success status of thread creation and each message sent.
22
 * @throws Error if the thread creation or any message sending fails, or if input validations fail.
23
 */
24
export async function main(
25
  discordBotConfigResource: DiscordBotConfiguration,
26
  channelId: string,
27
  threadName: string,
28
  firstMessage: string,
29
  messages: string[],
30
  lastMessage: string
31
): Promise<{ thread: boolean; messages: boolean[] }> {
32
  // First, validate threadName length
33
  if (threadName.length > 100) {
34
    throw new Error("Thread name must be 100 characters or less.");
35
  }
36

37
  // Validate firstMessage and lastMessage length
38
  if (firstMessage.length > 2000) {
39
    throw new Error("First message must be 2000 characters or less.");
40
  }
41
  if (lastMessage.length > 2000) {
42
    throw new Error("Last message must be 2000 characters or less.");
43
  }
44

45
  // Next, validate each message length in the array. This ensures all messages are checked before any API request is made.
46
  for (const message of messages) {
47
    if (message.length > 2000) {
48
      throw new Error("Each message must be 2000 characters or less.");
49
    }
50
  }
51

52
  // Initialize the result object
53
  const result = {
54
    thread: false,
55
    messages: []
56
  };
57

58
  // Construct the URL for creating a thread
59
  const createThreadUrl = `https://discord.com/api/v9/channels/${channelId}/threads`;
60

61
  // Prepare the request body for creating a thread
62
  const createThreadBody = JSON.stringify({
63
    name: threadName,
64
    auto_archive_duration: 60, // Automatically archive the thread after 60 minutes of inactivity
65
    type: 11 // Type 11 represents a private thread
66
  });
67

68
  // Prepare the request headers
69
  const headers = {
70
    'Content-Type': 'application/json',
71
    'Authorization': `Bot ${discordBotConfigResource.bot_token ?? discordBotConfigResource.public_key}`
72
  };
73

74
  // Attempt to create the thread by sending a POST request
75
  const createThreadResponse = await fetch(createThreadUrl, {
76
    method: 'POST',
77
    headers: headers,
78
    body: createThreadBody
79
  });
80

81
  if (!createThreadResponse.ok) {
82
    throw new Error("Failed to create thread");
83
  }
84

85
  // Parse the response to get the thread ID
86
  const threadInfo = await createThreadResponse.json();
87
  const threadId = threadInfo.id;
88
  result.thread = true; // Mark thread creation as successful
89

90
  // Function to send a message to the created thread
91
const sendMessage = async (message: string) => {
92
  // Construct the URL for sending a message to the thread
93
  const sendMessageUrl = `https://discord.com/api/v9/channels/${threadId}/messages`;
94

95
  // Prepare the request body for sending a message
96
  const messageBody = JSON.stringify({
97
    content: message
98
  });
99

100
  // Attempt to send the message by sending a POST request
101
  const sendMessageResponse = await fetch(sendMessageUrl, {
102
    method: 'POST',
103
    headers: headers,
104
    body: messageBody
105
  });
106

107
  // Check for rate limit response before checking if response is OK
108
  if (sendMessageResponse.status === 429) { // 429 is the HTTP status code for Too Many Requests
109
      const retryAfter = parseInt(sendMessageResponse.headers.get('Retry-After'), 10);
110
      console.log(`Rate limit hit, retrying after ${retryAfter} seconds.`);
111
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); // Wait for the duration specified by Retry-After
112
      return sendMessage(message); // Attempt to resend the message
113
  }
114

115
  if (!sendMessageResponse.ok) {
116
    throw new Error(`Failed to send message: ${message}`);
117
  }
118

119
  // Record the success status of sending each message
120
  result.messages.push(true);
121
};
122

123
  // Send the first message
124
  await sendMessage(firstMessage);
125

126
  // Send messages in the array
127
  for (const message of messages) {
128
    await sendMessage(message);
129
  }
130

131
  // Send the last message
132
  await sendMessage(lastMessage);
133

134
  return result;
135
}