Is it possible to generate the default thread name from a message with djs?

Discord has some algorithm in place to generate a default name for every thread created on a message. AFAIK this title cannot be made with the API since the name is required on POST/channels/{channel.id}/messages/{message.id}/threads. Is it possible to do these transformations with DJS, or does anyone know another library that does it?
31 Replies
d.js docs
d.js docs2y ago
• What's your exact discord.js npm list discord.js and node node -v version? • Post the full error stack trace, not just the top part! • Show your code! • Explain what exactly your issue is. • Not a discord.js issue? Check out #useful-servers.
LeMorrow
LeMorrow2y ago
Two more examples of why it would be annoying to implement myself by reverse engineering it:
Stealth
Stealth2y ago
You want to thread name to be set? Or have a placeholder like discord does before making one If you want the first one, just listen to “threadCreate” event and then set the name of the thread that was created. The title is made to the reference of the first message of the thread/the message that the thread was started with and i think uses the max character limit to shorten in
LeMorrow
LeMorrow2y ago
I want the placeholder like Discord does before making one My bot will be the one creating the thread, based on a message So I want to generate it the same way Discord does with the API you are forced to provide a name (unlike how it is in the desktop client where it is optional)
Stealth
Stealth2y ago
Oh I understand what you’re saying, i think whenever you’re not setting the name from discord client it is optional because most likely they generate that title that I mentioned from the client not the backend
LeMorrow
LeMorrow2y ago
Yeah I think so too
Stealth
Stealth2y ago
So the backend always requires it
LeMorrow
LeMorrow2y ago
This is how I think their algorithm works (based just on my reverse engineering): If there is an image, use it's alt text If there is an embed, use the title of the embed Otherwise take one word at a time from the original message. As soon as adding a word would make the title go over 40 characters, discard that word, and the title is done. If there is only one "word" of 40+ characters long, use the first 40 characters and append an elipsis
Stealth
Stealth2y ago
Yes That is how it works
LeMorrow
LeMorrow2y ago
And this is one of those things that can change at any time... it feels hacky to hard-code it into the bot, y'know?
Stealth
Stealth2y ago
I don’t think you can hardcode that into the bot
LeMorrow
LeMorrow2y ago
Why wouldn't I be able to If I have message content I can access everything Discord has access to
Stealth
Stealth2y ago
I mean like i said you can do that yes But all I’m saying is you wanted it to have a placeholder Which is not possible
LeMorrow
LeMorrow2y ago
Not sure what you mean by placeholder in this case I want to create a thread based off of a message
d.js docs
d.js docs2y ago
method GuildChannelManager#create() Creates a new channel in the guild.
LeMorrow
LeMorrow2y ago
The name of the thread should be the same as the name it would've gotten by Discord if a user created a thread on the message manually This is what I am looking for how to do
Stealth
Stealth2y ago
Yea then try that and set the name property inside the create argument object
LeMorrow
LeMorrow2y ago
So I am stuck with having to reverse engineer their default name algorithm?
d.js docs
d.js docs2y ago
interface GuildChannelCreateOptions Options used to create a new channel in a guild.
Stealth
Stealth2y ago
Ohhh I don’t think that is djs related that’s JS itself
LeMorrow
LeMorrow2y ago
wut I'm not asking how I would implement it
Is it possible to do these transformations with DJS, or does anyone know another library that does it?
It's specifically a DJS question I'm asking if there's some helper method somewhere that does this already in DJS
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
LeMorrow
LeMorrow2y ago
👍 thank you
Stealth
Stealth2y ago
That’s what i said, you have to make the algorithm yourself Cuz djs doesn’t seem to have it
monbrey
monbrey2y ago
No, discord.js does not have this Other than just giving you the message content You can truncate that wherever you like
LeMorrow
LeMorrow2y ago
Thanks for confirming. Guess I am stuck with hoping that discord changes their API and make the name optional just like how it is in the client Made a feature request about it
monbrey
monbrey2y ago
I really don't think this is much of an "algorithm". I expect that the placeholder thread name is done client side and sends the value to the API
LeMorrow
LeMorrow2y ago
I don't mean "algorithm" as in some big complicated thing. Just a sequence of steps it takes. This is what I have so far from how it works
monbrey
monbrey2y ago
Yeah fair enough
LeMorrow
LeMorrow2y ago
For future reference if anyone stumbles upon this: https://github.com/discord/discord-api-docs/discussions/5326
GitHub
Starting a thread from a message should not require name · Discussi...
When you are creating a thread on a message in the client, the name of the thread is optional: However, in the API, the name is not optional. It would be nice to make it optional so that we can use...
LeMorrow
LeMorrow2y ago
Thanks again Untested:
private generateDefaultThreadName(message: Message): string {
const attachmentText = message.attachments.first()?.description;
if (attachmentText) return attachmentText;

const embedTitle = message.embeds.length > 0 && message.embeds[0].title;
if (embedTitle) return embedTitle;

const words = message.content.split(" ");
let output = "";
for (const word of words) {
if (output.length + word.length > 40) break;
output += word + " ";
}

if (words.length > 0 && output.length === 0) {
output = words[0].substring(0, 40) + "...";
}

return output.trim();
}
private generateDefaultThreadName(message: Message): string {
const attachmentText = message.attachments.first()?.description;
if (attachmentText) return attachmentText;

const embedTitle = message.embeds.length > 0 && message.embeds[0].title;
if (embedTitle) return embedTitle;

const words = message.content.split(" ");
let output = "";
for (const word of words) {
if (output.length + word.length > 40) break;
output += word + " ";
}

if (words.length > 0 && output.length === 0) {
output = words[0].substring(0, 40) + "...";
}

return output.trim();
}
Tested it now and made sure it worked. Turns out Discord handles link/embed names different from message content names. Worked in the couple cases I tested it with.
// This is an approximation of Discord's own algorithm done in the Discord client
// https://github.com/discord/discord-api-docs/discussions/5326
private generateDefaultThreadName(message: Message): string {
const attachmentText = message.attachments.first()?.description;
if (attachmentText) return this.clampWithElipse(attachmentText, 40);

const embedTitle = message.embeds.length > 0 && message.embeds[0].title;
if (embedTitle) return this.clampWithElipse(embedTitle, 40);

const words = message.content.split(" ");
let output = "";
for (const word of words) {
if (output.length + word.length > 40) break;
output += word + " ";
}

if (words.length > 0 && output.length === 0) {
output = words[0].substring(0, 40) + "...";
}

return output.trim();
}

private clampWithElipse(input: string, maxLength: number) {
const output = input.substring(0, maxLength);
return input.length > maxLength ? output + "..." : output;
}
// This is an approximation of Discord's own algorithm done in the Discord client
// https://github.com/discord/discord-api-docs/discussions/5326
private generateDefaultThreadName(message: Message): string {
const attachmentText = message.attachments.first()?.description;
if (attachmentText) return this.clampWithElipse(attachmentText, 40);

const embedTitle = message.embeds.length > 0 && message.embeds[0].title;
if (embedTitle) return this.clampWithElipse(embedTitle, 40);

const words = message.content.split(" ");
let output = "";
for (const word of words) {
if (output.length + word.length > 40) break;
output += word + " ";
}

if (words.length > 0 && output.length === 0) {
output = words[0].substring(0, 40) + "...";
}

return output.trim();
}

private clampWithElipse(input: string, maxLength: number) {
const output = input.substring(0, maxLength);
return input.length > maxLength ? output + "..." : output;
}