#archive-library-discussion

25217 messages · Page 25 of 26

warped crater
#

it's just a global option you pass on instantiation

tacit crypt
#

Hmm. That ones tough

warped crater
#

yeah catHmm

#

is there a specific reason it's not a per-req option as well

tacit crypt
#

can't we just

#

make proxy always return 429s

#

and let the client using the proxy handle the parsing/error throwing?

warped crater
#

well, the library itself exposes a middleware function that takes in a REST instance that is already instantiated

#

so by all means, users are welcome to do that and it's easy to accomplish

#

if we end up exporting a binary/docker image that just starts up a v simple proxy to fulfil most people's needs

#

we could default to that, yes

tacit crypt
#

this is more a crawl question but from my pov

my worker rest instance that connects to the proxy has its own rejectOnRatelimit
Proxy always tells me a 429 happened.
My worker instance decides to throw it or not

warped crater
#

yea that makes sense

#

you might want to retry on the worker side

#

we can figure out such default behavior later when we actually make those binaries, but for now

#

back to the original topic

#

could REST support per-request rejectOnRatelimit?

#

i actually feel like this has more diverse usecase

tacit crypt
#

better question is should it support that

warped crater
#

well i can think of why it'd be good

#

the age old problem

#

discord bumps a ratelimit to hell and we don't know, our bot starts leaking memory because the poor sequential bucket handler gets queued requests faster than it handles them because of the ratelimits

#

we had this happen with channel names (no, not an obnoxious clock feature)

#

and we had no clue what was going on

#

we were queueing, say 3-4 reqs per 10 minutes and the limit is 2/10min

#

so I could it see it being beneficial to pass in the option for long limits that you know you don't want to wait for

warped crater
solemn oyster
#

Yes, check the reviews

#

I bumped those a bit too high, they should be using the same version as 13.7.0 does, which is 0.30.0

warped crater
#

ah mb

#

I was looking at it before vlad reviewed that

warped crater
#

hi so

#

is there any reason declaration source maps are not enabled?

#

it would make working with the monorepo a shit load easier since VSCode "Go To Symbol" would actually take me to the definitions

warped crater
#

hmm, the only thing proxy can't forward rn is headers for non-2xx status codes - DiscordAPIError has most of the relevant info (status text, status message, body etc) but not headers

I was thinking of how this could be accomplished and the only way would be to have REST#raw not throw - but rather return responses even when they're not 2xx. I think this would actually be desirable behavior catHmm? cc @wild flax @tacit crypt

#

all though that becomes.. stupidly complicated to accomplish meguFace

dawn merlin
warped crater
#

it works for me in my monorepo 👀

#

lemme test real quick to see if it works with djs (all though I don't see why it wouldn't), and if so I might PR

#

while I was working on that

#

actually confused why that's in the repo - esp. given VSCode gives no easy option to bypass that once it's a workspace setting

#

well, after some research seems tsup doesn't support declaration source maps properly, so there goes that dream

golden mortar
#

I added that with the intent to remove it once the pr was ready but then crawl was fine with it staying in

warped crater
#

Is there anything stopping #7929 (REST#raw) from being merged? just needs space to approve, right?

warped crater
#

thanks for the merge. #7925 is now ready for review owoah

#

I've also added a section for current minor caveats that don't seem easily fixable but that we may or may not want to address

#

I'm also gonna be running some proper tests on it today to make sure it all works

wild flax
#

I only skimmed the code

#

Is this like a full binary solution

#

Or is this just a middleware type of thing

warped crater
#

unsure how we wanna deal with binaries since djs has no precedent doing that afaik

#

would it even be in the package folder but ignored from npm publish

wild flax
#

If it’s a library yeah like a middleware

warped crater
#

oh hey im green now

wild flax
#

But idk maybe we should make a separate repo

#

Where we make it a binary and docker image or smth

#

Because if it was a ready to deploy solution too, it’d be kinda nice

warped crater
#

yea that's what I'm thinking too

#

so there's like

#

2 exported functions that help you populate a ServerResponse from either an error or a 200 response from discord so you can make your own stuff

#

and then there's a proxyRequests middleware

#

that just calls REST#raw in a try..catch

#

and calls the appropriate method

#

and ends the response

wild flax
#

Yeah idk if you want to wrap this around a node http server

#

Lmk

#

I can make a repo for this

warped crater
#

that's probs how the default binary would work no?

#

express etc seems like too much just for this

wild flax
#

Yeah

warped crater
#

yea ok

#

yea im setting up a little test project locally rn to see if it all works

#

and once we merge we can get a repo going for common usecases

wild flax
#

There is something else but idk if it’s in node already

#

They did rewrite the http with some new thing

#

Kinda like undici

warped crater
#

personally what i'll be using for my bot is something that a) logs & collects analytics and b) caches since I like dealing with cache at the proxy level much to your distaste :^)

wild flax
#

But idk if they merged it into actual node yet

#

Idk if it should cache things

warped crater
#

yea def not the default one kek

#

that's mostly a me thing

#

I guess the first one will just proxy and nothing else on top

#

and then people can like

#

"hey I have my own custom one that does X"

#

and if X is popular we can

#

add more, boom

wild flax
#

sure

warped crater
#

@wild flax 👀

// proxy.js - this will be our binary minus the worker stuff
import { createServer } from 'node:http';
import { proxyRequests } from '@discordjs/proxy';
import { REST } from '@discordjs/rest';
import { parentPort } from 'node:worker_threads';

const api = new REST({ version: '10', rejectOnRateLimit: () => true }).setToken(process.env.DISCORD_TOKEN);

const server = createServer(proxyRequests(api));
server.listen(parseInt(process.env.PORT, 10), () => {
    parentPort.postMessage('ready');
});
// index.js
import { Worker, SHARE_ENV } from 'node:worker_threads';
import { Client, IntentsBitField } from 'discord.js';
import { ProxyAgent } from 'undici';

const client = new Client({
    intents: [IntentsBitField.Flags.Guilds],
});
client.on('ready', () => {
    console.log('ready');
    process.exit(0);
});

client.rest.setAgent(new ProxyAgent(`http://localhost:${process.env.PORT}`));

const restWorker = new Worker('./proxy.js', { env: SHARE_ENV });
restWorker.once('message', () => {
    console.log('rest worker ready');
    client.login(process.env.DISCORD_TOKEN);
});
➜ node index.js
rest worker ready
ready```
#

works now

#

I'll probs test some other stuff here and there but generally speaking at least the gateway connects kek

wild flax
#

Why does it use workers

warped crater
#

idk that was just for my test

#

I could've just booted it as its own process lol

#

but I think some people might be inclined to boot it in a worker if they're just using proxy to work around the /gateway/bot ratelimit we were talking about

#

if their bot is a monolith where they only start one process anyway it's probs easier for them to throw rest into a worker

warped crater
#

alright, I'm actually done with my PR now unless changes are requested

sleek kelp
#

Shouldn’t the threadCreate, threadDelete and threadUpdate events be integrated into channel<events>. Then the user can check if the channel is thread and do whatever

#

I’m not sure if this is already implemented since I don’t follow the GitHub updates that often

copper laurel
#

We don't change or manipulate events, we follow the Discord API which has them separate

quiet viper
#

Does not account for emojiCreate and emojiDelete...

copper laurel
#

Huh, good point, no idea why we do that, though its kinda the opposite example

#

Thats one event being split out rather than multiple events being merged together

sour ferry
#

I have nothing to say about it, just look at the pictures.

warped crater
#

confused

visual hornet
rough roost
#

pretty sure you are supposed to parse #fff as #ffffff

visual hornet
#

but that's not exactly a hex string, that's a shorthand hex string. tons of things don't support it.

copper laurel
#

Yeah, not standard

visual hornet
#

hmm can't we just validate with /^#?[\da-f]{6}$/i
and if that doesn't match then throw an error

fervent walrus
#

cant install stuff into main branch. Need to push commits on the pr

[versions]
yarn -> 3.2.0
node -> 16.15.0

#

!node_modules 🫂

real jetty
warped crater
#

Mon's message was a general statement

unique axle
#

i agree, let's stop doing that firFine

ruby terrace
opaque vessel
#

Still voting for we should leave it as it comes from the API

copper laurel
#

Delete node_modules and start again

fervent walrus
# copper laurel This isn't a support channel

Yes but I have to commit to my pr and I cannot resolve this issue and it clearly seemed djs issue by reading the errors. This happens only on main branch.
Also there is no node_modules if you see the ss and trying to install node_modules using yarn or yarn install throws the errors from the above ss.

Idk how this aint library related.

coral cave
#

in the slash command option classes, you all really need to adjust the names of the addChoice and addChoices methods. They're super easy to mistake particularly if your editor has autocomplete, and the error message you get from the validation is incredibly vague - makes debugging it a nightmare

visual hornet
#

i think that'll be resolved along with the addField/addFields thing for embeds

coral cave
#

I'm happy to hear that 🙂

visual hornet
#

there's been a lot of discussion around their signatures and inclusion

unkempt bear
#

addChoice has already been removed in the main version of the builders. I believe addField will follow suit

coral cave
#

so in the future you'll have to add all choices as an array of string pairs, right?

unkempt bear
#

They take a rest param so not an array, but yes it will take APIApplicationCommandOptionChoice params

copper laurel
#

At the moment the latest version only takes arrays but I think we're adding back support for both

unkempt bear
#

stable doesn't, but main does

solemn oyster
honest barn
ember steeple
#

because in paython they use snake case

visual hornet
#

^ and dapi uses python

tacit crypt
visual hornet
#

hasn't there been talks of like

  • camelCase along with snake_case
  • seperate camelCase and snake_case classes
  • camelCase conversion method
    and they all basically ended with too complicated and unnecessary?
outer raven
#

not really, snake_case and camelCase are supported on most things atm

outer raven
#

what's the URL for the new discord-api-docstypes website?

tacit crypt
#

Patience

#

lol

analog oyster
#

there's a new discord-api-docs website?

tacit crypt
#

Well vercel ruined the surprise

#

But please wait till I announce it properly bc I'm still setting some things up

outer raven
#

sorry thought it was live already!

tacit crypt
outer raven
#

aye!

#

where can we give feedback about it?

tacit crypt
tacit crypt
#

oh

#

Rodry mistyped to heck and back

outer raven
exotic leaf
ornate topaz
#

doesn't that require oauth2 for anything about nitro to be sent to you?

exotic leaf
#

Ooh thank you

exotic leaf
dawn merlin
#

I’m pretty sure the premium type is sent in the user json can’t remember

outer raven
#

logged in user ye, not external

ornate topaz
mighty bough
visual hornet
#

shallow clone probably

dawn merlin
#

pretty much, if we returned this.data, and someone modified the json from toJSON it would also modify the Embed props

copper garden
#

Wouldn't editing the fields, footer, or any property that is a ds still be affected tho?

dawn merlin
#

Yeah it’s a shallow clone not a deep one

echo laurel
#

Hello 🙂
I reinstalled my project with keeping the "discord.js": "^13.6.0" dep, but I had the bad surprise to see my code break. I then eventually figured out the cause was my ApplicationCommandOptionChoice usage (I was sending the old [string, string] array) + version update to 13.7.
So my question is about releasing : how a breaking change like this was only refered as a documentation update in the github release ?
(Or did I missed something)

Thx 🙂

copper laurel
#

Those are re-exported from an external dependency, @discord/builders which doesn't have a stable semver major release yet

echo laurel
#

Oh ok my bad I did not notice that

#

Anyway I should not have break my lock file, so it should not happen again

#

But I might set stricter dep constraints just in case

warped crater
#

hm

#

"stable semver" refers to 1.x releases. builders is at 0.x so therefore minor updates to builders can contain breaking changes - but I'm wondering how this applies to d.js re-exporting Thonk

#

in my mind this feels like it should be breaking to d.js but..

echo laurel
#
  • with locked deps it should not break often
sonic condor
#

Hi, is there a new djs version coming anytime soon which would require rewriting your bot?

real jetty
sonic condor
real jetty
#

There are no ETAs, it will be released when it's ready

sonic condor
#

Uh, alright, thanks

outer raven
#

@tacit crypt you never really suggested a better name yourself but I’m confused: do you agree with it or not?

tacit crypt
#

I agree with the PR, and if a better name can be found then even better

#

But from my pov its really not a blocker

#

or it shouldn't be I should say

outer raven
#

Alright thumbs

mighty bough
#

Why is name separate from the options argument in GuildChannelManager#create()? Why can't it be inside the object?

unique axle
#

required vs. optional

dawn merlin
#

I mean it could be in the object as a required prop

unique axle
#

that was the reasoning afaik

mighty bough
#

There are some inconsistencies for "required vs. optional" like embed footer text and client intents I'd say

dawn merlin
#

I personally would prefer it be a single object like channel.send and such shrug

vernal rose
#

There is a pr ig

mighty bough
#

I looked for one but iirc it got closed

dawn merlin
vernal rose
mighty bough
#

Alright cool, 3 approving reviews

outer raven
#

ahyes the pr with the best english

unique axle
#

they literally state that they're having issues with english in their opening post, there is absolutely no reason to bring that up again

outer raven
#

Someone could at least fix it, some sentences don’t make sense at all

raven wind
real jetty
#

Not sure if bug, but - You can send embed with empty message content, but if you have a message that has content and you try to edit it into embed, it will throw error that message content must be non-empty string

copper laurel
#

Are you trying to set content to an empty string, or to null?

copper laurel
#

Try null, on latest @dev release

real jetty
woven delta
#

Just wanted to stop by and send a big THANK YOU, from me, you guys are doing great things and made my discord dev a piece of cake
❤️

bitter peak
#

What could be causing this error? Fresh checkout of the main branch, ran yarn --immutable, yarn build, then yarn test

#

also

loud jayBOT
#

pr_open #7985 in discordjs/discord.js by memikri opened <t:1654052875:R> (review required)
feat(Client): wait for ClientReady event before resolving login
📥 npm i memikri/discord.js#feat/defer-ready-event

dawn merlin
# bitter peak also

Shouldn’t you be using the ready event to wait for ws stuff to be ready?

bitter peak
#

Well my though here is that this makes the login() method more useful, since currently it doesn't really matter too much and its return value is useless

#

This also would make it much nicer to use in a top-level-await context, for example

dawn merlin
#

But what if the client isn’t considered ready?

copper laurel
#

login and ready are not the same thing

bitter peak
#

Well that's what the PR would be solving

#

yes but I'm proposing to make them the same thing

#

I can't think of any compelling use-case where you would want to use the client when it is between logging-in and ready

copper laurel
#

I still disagree that we should abstract it away when users can promisify the ready event themselves easily anyway

ruby terrace
#

the client should be considered logged in as soon as it identifies, which is not the same thing as being ready

copper laurel
#

You can start making API calls after being logged in but before the client is ready - its just caches that aren't populated

ruby terrace
#

tbf you can make API calls without the gateway at all

copper laurel
#

Well yes, but login is the method that sets the client token

ruby terrace
#

I think you can also start sending gateway opcodes before receiving ready, though not really sure on that one

wild osprey
#

wha

dawn merlin
#

also

await client.login(process.env.DISCORD_TOKEN);
const [readyClient] = await once(client, 'ready');

console.log(`Logged in as ${readyClient.user.username}`);

Is pretty easy with TLA or an IIFE

bitter peak
dawn merlin
#

It doesn’t

bitter peak
#

(hence why I was calling its return value useless earlier)

dawn merlin
#

It returns the ready client back

#

More of type distinction but yeah

bitter peak
#

Ah got confused with login

#

Sorry

dawn merlin
#

No worries

bitter peak
#

I made the PR that added that type distinction so I should've known that one lol

white hedge
#

Is there any PR for Text in Voice?

#

I mean, for v13, not v14

real jetty
#

not yet from what i know

white hedge
ornate topaz
#

We recently landed 13.7.0, which fixed some crashes for TiV.
Creating new PRs for v13 will just push back eventual v14 release, which is starting to get slightly overdue. The hypothetical 13.8.0 would either get delayed by multitude of new PRs for backporting / adding stuff just to squish it into a release, or it would have only a fast-tracked TiV support. Doing the latter wouldn't make that much sense, as v14 already fully supports it, and the former makes entire situation worse.

neon minnow
tacit crypt
#

Thats not really useful for this channel 😒
If you have a bug report, please report it on our GitHub. If it was fixed already in a newer version, update and see if the issue still happens

neon minnow
#

But this of result of the discord.js stupid version system where next version results in lower mainaonence of older when newer is still not stable

#

And this happens over and over

nova quiver
#

v13.7 is stable

neon minnow
#

But in result of v14 development there are many features missing

nova quiver
#

thats the point of new versions they cant add everything to 1 version if they update they make new versions

#

do you understand?

opaque vessel
#

discord.js stupid version system
Yikes. It's semver dude, it's literally a standard

solemn oyster
#

Please calm down, there's no need to rant about our versioning system

nova quiver
tacit crypt
#

And sometimes maybe we do have bugs that we haven't encountered before. It happens shrug . Most helpful thing you (or anyone that encounters a bug) can do is open a GitHub issue with reproduction steps, the version you encountered the issue on and let us triage it

neon minnow
tacit crypt
#

I don't even know how you encountered that issue. Maybe your next steps should be telling us what you did / how you encountered that issue so we can look into it

nova quiver
#

maybe you don't use version 13.7

white tulip
#

I just had an idea: What if instead of the cache storing the message object, aka the object with all the helper reply functions and such, what if it'd just store the actual data, and when an event is called or someone uses cache.get or .fetch, the lib will just construct the obj then and then return it. The idea is that that'd help with saving memory

visual hornet
#

there's a tradeoff between memory and efficiency, and that seems like it would lean way too much towards the memory side and reduce efficiency

solemn oyster
#

But we won't do that way, rather, we'll have structures with a data field

ornate topaz
#

this also sounds like it would only support get or has methods, and filtering or finding would mean constructing everything

quiet viper
white tulip
#

Ah ok

solemn oyster
#

That's why we're doing a hybrid

#

So we get most of the memory benefits, without sacrificing performance

white tulip
#

How was it done before the data field?

ornate topaz
#

like it is done currently?

white tulip
#

re

#

O the properties were accessible at the top level

ornate topaz
#

wouldn't they potentially still be?

white tulip
#

Which just get from the data prop

#

I’ll check

#

Hm is it so that the prs haven’t been pushed yet

solemn oyster
#

We have an entire issue that's very elaborated on this

white tulip
#

And the interaction one

solemn oyster
#

The issue targets TSR

white tulip
solemn oyster
#

Yes

white tulip
#

Ah, I thought you meant it was done 😅

solemn oyster
#

No, TSR is coming out after v14

solemn oyster
white tulip
#

Ah TSR = Typescript rewrite

tacit crypt
#

TSR will happen sometimes after v14 btw, not necessarily a v15 (it's a massive undertaking)

stray delta
#

what reason would something be declared in BaseXChannel as opposed to XChannel?

outer raven
#

e.g. BaseTextChannel is extended by TextChannel and NewsChannel

stray delta
outer raven
full summit
#

Going to take a shot in the dark and ask here. How does one fork the main library and install from github with the new setup?

I reset a branch hard to the main lib, didn't do anything else, and it failed the 'post install' script.

Deleted that post install script from the 'scripts' in package.json and it installed but then trying to run a bot results in 'cannot find module 'discord.js'' same with 'cannot find module @discordjs/discord.js'

I am at a loss at this point on what the heck i'm supposed to do.

full summit
#

You can do one of the following solutions if you have the fork downloaded locally:

#

this doesn't help for hosted bots, unless you're assuming i have to do the same thing for each bot i host

dawn merlin
#

is your bot on a VPS?

full summit
#

i have 3, and 2 local test bots

dawn merlin
#

you can link your fork on all of the hosts

#

you'd clone your fork on the servers and then link to them

full summit
#

sounds like fun

#

So now i fall back on what the heck does it mean by
Use yarn link inside the packages/discord.js directory and in your application's folder.

#

i'm going to assume i need to create a folder and i can name it whatever the heck i want in the node_modules folder and then use link with it?

dawn merlin
#

I'm not familiar with linking in yarn, but you can have the repo cloned anywhere you just need to provide the path when linking

full summit
slate nacelle
#

In discord.js' folder you run yarn link and inside of your project's you run yarn link discord.js iirc

full summit
#

i figured it out, it was demanding a 'name' property in package.json

#

and also no

#

yarn link just posts the 'help' for link

#

and of course the link did absolutely nothing

#

This command is run in the package folder you’d like to consume. For example if you are working on react and would like to use your local version to debug a problem in react-relay, simply run yarn link inside of the react project.

Unknown Syntax Error: Not enough positional arguments.

$ yarn link [-A,--all] [-p,--private] [-r,--relative] <destination>```
#

documentation is so much fun when it's invalid

dawn merlin
#

which version of yarn are you using?

full summit
#

okay so i ran yarn link in my bot folder

#

and it worked great

dawn merlin
#

those docs apply to yarn 1.x, but in yarn 3.x, you just do yarn link [path to package]

full summit
#

so that must mean that packages/discord.js is probably already registered to some name

#

nvm it's 3.2.1

full summit
analog oyster
#

the yarn version in the discord.js repo is 3.2.1

#

but if you didnt install it in your own folders you wont have that version

full summit
#

published versions of yarn only go up to 2.4.3

#

"this project is configured to use yarn" so i forced to use yarn now am i? this is very inuitive

tacit crypt
#

The simplest way to actually get your local fork / any fork in your other repos is packing the discord.js module and installing from the pack shrug

wild flax
#

^ this pretty much

full summit
#

well then, lets see how overly complex this solution is then

#

cause so far i've hit a dead wall

full summit
#

unless i'm stupid and this isn't what you mean by 'install from pack'

tacit crypt
#

Well you'll probably also need to pack collection, install it first, then the djs pack

wild flax
#

pretty much anything that djs uses

full summit
#

it also needs rest... so i suppose i ahve to do that one as well?

#

so can i not just pack the entire project and install from it?

#

or is it literally just one by one

wild flax
#

don't think you can

full summit
#

fun

wild flax
#

pretty niche use case

#

¯_(ツ)_/¯

tacit crypt
#

I mean, unless you're trying some local changes yourself, you can just install the @dev versions of our modules

full summit
#

i have local changes

#

though i do think, if i'm especially lazy, i can just upload the tgz files to github and then install them when i pull

wild flax
#

don't we allow to configure pretty much anything already anyway

#

what is still missing people need a fork for

full summit
#

there are several changes that i have that make my life insanely easier

#

plus i've found several interesting bugs that are so much fun to diagnose

#

maybe they were already found and i needed to simply update my fork

#

but then i fall back to 'i have several changes that make my life easier'

#

also

#

installed collection

#

tried to install rest, said collection doesn't exist

#

:D

wild flax
#

yeah I honestly don't know if its even easily possible

full summit
#

that's 4 hours of my life i'm not getting back, fantastic

tacit crypt
#

Can you try it with npm instead?

full summit
#

keeps posting this error:

wild flax
#

Yeah because we use the workspace protocol

outer raven
#

If djs used yarn v1 you could link packages in the monorepo with themselves but in v3 they removed that possibility

#

Never really understood why djs moved to v3 tbh, it doesn’t give any benefit

solemn oyster
#

It does, many of them, including performance and plugins (which we use)

outer raven
#

which plugins

warped crater
#

have you thought of looking at the .yarn/plugins dir

wild flax
#

Also v1 is purely in maintenance mode lol

warped crater
#

thanks...? I was telling Rodry to have a look at it

nova quiver
#

dont worry i looked and i sent

ornate topaz
#

but the question wasn't literally asking "what's in there", but was in form of "did you try looking there yourself before you complain that we moved to newer version"

outer raven
#

Judging from all the activity on github it would seem like v14 is close, is that right?

unique axle
#

no eta

stray delta
#

it's ready when it's ready ™️

stray delta
fervent walrus
#

Are we gonna have another v13 release for the zombie connection pr?

honest barn
#

looks like it

outer raven
#

@dawn merlin seeing as you made a PR to remove a feature I added could you let me comment on it please

outer raven
#

Seems like APIAttachment doesn't include the property name, making it impossible to use the AttachmentBuilder and give the attachment a name, could someone fix this?

#

not sure if the issue is in dapi types or djs

outer raven
#

can't commit due to this, what should I do?

tacit crypt
#

run yarn build

outer raven
#

right yeah that fixed it

outer raven
wild flax
#

might as well fix the other error too

#

files?: (BufferResolvable | Stream | JSONEncodable<APIAttachment> | Attachment | AttachmentBuilder)[]; in all places is missing AttachmentPayload

#

which didnt allow you to construct an attachment with files: [{ name: 'some_name.txt', attachment: Buffer.from(xyz, 'utf-8') }]

outer raven
#

will add that

wild flax
#

But tiv is out

stray delta
#

that's not what i'm asking

wild flax
#

We usually wait yes

#

But if discord is too lazy to merge stuff that won’t change because it’s a live deploy

#

We usually don’t care

stray delta
#

kk

stray delta
#

webhook messages shouldn't be cached if the bot can't see them right? (i.e. send through WebhookClient)

vernal atlas
#

i suppose there isnt much of a reason to cache them no

outer raven
#

Seems like v13.8.0 added a breaking change, was this intentional?

wild flax
#

Probably not

#

@vernal rose I don’t think we can use cliff jumper here

#

We don’t want or need any of its features

vernal rose
wild flax
#

Or smth

opaque vessel
#

Well I assume the event was always emitting a channel with a thread manager, so receiving a message in a voice channel will break things, as you didn't need to check if a thread manager existed before

outer raven
wild flax
#

I guess

#

But it’s either that or no TiV

outer raven
#

True ig

wild flax
#

I guess it’s a compromise we shouldn’t make, but we didn’t want a v13.8 in the first place

#

It’s risky to update, but I think for those who really want to stay on 13 worth the risk

outer raven
#

If v14 is near it could’ve just been released then but idk if it is

wild flax
#

It’s not

#

Builders needs a rework

#

Permissions 2 isn’t merged

#

Neither is the object input one

#

Which are all breaking

warped crater
#

is automod also breaking

#

havent checked if that breaks anything for whatever reason

wild flax
#

If no one backports it

warped crater
#

rephrased

wild flax
#

Right, idk didn’t look yet

warped crater
#

meant "is it breaking so it needs to be in 14.0.0"

#

so like, does it block v14

#

icic

opaque vessel
#

So far that one is a minor

#

Don't think anything will be breaking in it

#

They change that PR a lot though

stray delta
# vernal atlas i suppose there isnt much of a reason to cache them no

how is the caching logic even supposed to work? If the bot can indeed see the channel where its' own webhook message was send it gets two requests for trying to add to cache, one from returning the API request from and one from the bot actually being in that channel, if the bot tries to parse the APIMessage it crashes because it doesn't have the guild_id field at all (and this.chanels to resolve)

#

can i just PR a revert for the webhook APIMessage -> Message returns and not try to add it to cache like before? 7917 causes webhooks to break entirely cause of ^

loud jayBOT
dawn merlin
#

Yeah it’s either reverting that PR or making the channel getter on a message nullable

stray delta
#

well it's not really nullable, it's just that the getter incorrectly assumes client to not be a WebhookClient so the channelmanager doesn't exist to resolve from

dawn merlin
#

yeah but it even if the Webhook client had a channel manager it would be null, so it also returns null for regular clients if your bot isn't in a guild (which is misleading).

stray delta
#

probably better to return APIMessage then yeah

#

same thing applies when returning the message, it could never add it to cache because this.client is a WebhookClient so it always returns APIMessage

white hedge
#

Serious question: Are the localized commands working?
Because I add them with the edit function, but when I refresh my cache and fetch the commands again, the localizedName and localizedDescription properties shows up as null

#

From what I'm reading in the Discord API documentation, these fields are not sent unless the client requests them (using the withLocalizations option of the fetch method), but this method only returns the fields to me if I have previously used the method edit (or create) to add those fields. But if the cache disappears (for example, by restarting the bot), they return to null on fetch

#

What is the point of being able to add these fields, if they cannot be obtained later?

ruby terrace
#

just poorly typed

#

(technically not possible, but ya never know)

white hedge
outer raven
#

the API hasn't changed idk why it isn't on stable discord yet but it works as-is, no warning needed

tacit crypt
#

Localization is already available for commands to set in advance, the client support is supposedly coming sooner than later

white hedge
tacit crypt
#

Localizations can be set but your client won't render them

white hedge
#

You mean, on a user client (in the graphic interface)?

solemn oyster
#

The client we all use to interact with Discord

#

Localised application commands are still an experiment, so everyone sees what's on name and description

white hedge
solemn oyster
#

Client and API are two different things

#

We simply support everything the API supports

#

But what the Discord Client supports, is up to Discord, it has its own milestones and stuff

copper laurel
#

But if in not mistaken, what you're saying is that when you fetch commands, via the API in discord.js, you don't get the localisations back in the command object?

outer raven
#

have directory channels been released publicly on the API? I saw them on 13.8 for some reason

tacit crypt
#

invites can point to them

copper laurel
#

They're part of school hubs iirc

opaque vessel
#

Directory channels have been documented for a few months now

dawn merlin
copper laurel
#

@white hedge were you setting that when fetching?

white hedge
outer raven
opaque vessel
#

A directory channel is a channel containing guilds within a student hub

#

So a student hub is all you will ever find it in

white hedge
real jetty
#

where can i find a minifed version of discord.js

wild flax
#

why

wild flax
mighty bough
#

I think Collection#find() and other methods that take functions as arguments should have better errors.
Like if you provide a non-function to .find(), it seems to throw this error: https://sourceb.in/zh5x7UeCs6
but I believe it could be better, like fn provided for Collection#find() must be a function, received ${typeof fn}

opaque vessel
#

I believe running node with --enable-source-maps is what you're after? Also it doesn't error for me. Just ran <Collection>.find(3) and it returned undefined

mighty bough
opaque vessel
#

Ah okay, let me try with something populated

#

Same error as above

#

This boils down to what I said at the beginning, you want the --enable-source-maps option when you start your node

analog oyster
#

i was not using source maps

opaque vessel
#

Oh

#

Welp, flat out CNR then lmao

wild flax
#

I am unsure if we want that

#

The documentation states that it is identical to array.find

#

That does take a function too

shell lance
#

Because then it’s the fn.bind that produces that error

mighty bough
#

They tried .cache.find("name")

opaque vessel
#

Well as you can see, we're not getting that error... you probably should have tried that yourself too :P

wild flax
mighty bough
vernal rose
real jetty
warped crater
#

that's a fairly difficult question to answer, lol

#

if what you're wondering is if it's been dropped, the answer is no

#

it's a p big undertaking and some things just need to get ironed out before its completed

opaque vessel
#

I believe it's also waiting on /ws?

solemn oyster
#

Partly, yes, I have something in mind, but I have finals to take care of first

tender surge
#

Why is the api for awaitModalSubmit not so user friendly? Why does it throw instead of returning a empty value when nothing was collected? You're forced to catch the error and you can't even compare against it properly because there is no instance of the error exported

#

Seems like you can compare against it, but still weird it doesn't return a empty value like previous collectors did

#

Nvm the error instance is not exported so you can't compare

vernal rose
warped crater
#

👎 empty value is just poor behavior here IMO

#

albeit the error not being exported is not ideal either, will look into that in a bit if no one else gets to it by then

vernal rose
tender surge
#

But you could also control what throws an error in there through the errors property..

warped crater
#

yeah I see, errors being unexported is more of a library-wide problem

#

@solemn oyster would there actually be any concerns in exporting from src/errors?

#

it's a start but it actually wouldn't fully solve the issue lol.

#

this[kCode] = key; the error codes are locked behind a symbol so they'd still have to check against the .message

#

yeahhh this feels p hard to fix without an overhaul of how errors are handled honestly notLikeCat

solemn oyster
#

What if you made a code getter?

#

Or replaced the symbol property with a regular one

warped crater
#

that'd be a bit better I suppose, except our codes are just hard coded strings

#

e.g. in this case for the await modal thing

        else reject(new Error('INTERACTION_COLLECTOR_ERROR', reason));
#

they'd need to js } catch (error) { if (error instance of DjsError && error.code === 'INTERACTION_COLLECTOR_ERROR') { // do things } }

#

which is less than ideal

#

could honestly fit in something that redos errors in v14

warped crater
#

is there

#

im tired

#

may have missed it

#

oh, yes

    get code() {
      return this[kCode];
    }```
#

I see I see

#

👍 will make a PR about this tomorrow, all though it'll probably be another 500 lines changed like my last one as I attempt to rewrite this mess jynEHEH

slate nacelle
tender surge
solemn oyster
oak quail
#

oh right

#

i won’t be home for a while but i can add the note on sunday

#

is there any syntax or should i just add text to it

solemn oyster
#

I'm unaware if there's any syntax for it, since it's wrapped into a table, so possibly plain text nvm, thanks ckohen that

ruby terrace
#

warn blocks work in typedefs and parameter tables

loud jayBOT
warped crater
#

hm

#

yeah nvm, this should solve most issues

#

from here on out the only improvements we can make is make our errors more specific

#

e.g. INTERACTION_COLLECTOR_ERROR is used basically everywhere

#

it's hard to get much out of it sometimes

tender surge
#

ty

outer raven
#

@ruby terrace on #8065 why are there two awaits on this line? Are you awaiting a sort?

warped crater
#

appears so

outer raven
#

that doesn't do much does it

warped crater
#

absolutely nothing indeed

#

if I had to guess ckohen wrote await readdir(handlersDirectory) and then added .sort and just hit enter on the VSCode suggestion

#

which seems to always add another await in front since it doesn't check the methods' return type or something

outer raven
#

is interaction.options.getFocused().value meant to have all these possible types?

#

how can it be a boolean and undefined?

warped crater
outer raven
#

just string and number

#

you can't have autocomplete on boolean options

#

and I don't understand how it can be undefined

warped crater
#

is this v14

outer raven
#

yes

warped crater
#

hmm

#

yeah, good catch

#
export type AutocompleteOption = Pick<CommandInteractionOption, 'name' | 'type' | 'value' | 'focused'>;
#

it just keeps the value from CommandInteractionOption

#

where that type is accurate

outer raven
#

not sure what this CommandInteractionOption interface is meant to represent tbh

warped crater
#

an interaction option.

outer raven
#

but an option will always have value

#

otherwise it's not present

warped crater
#

🤷

#

don't know enough to be sure, probably future proofed

analog oyster
warped crater
#

there you go

#

dapi thing.

opaque vessel
warped crater
#

anyway, if you wanna, feel free to PR a fix to the typings

#

otherwise I'll do it in like 2hours

visual hornet
outer raven
warped crater
outer raven
#

do i just overwrite it in the autocomplete type?

visual hornet
outer raven
#

discord

warped crater
#

discord

visual hornet
#

oh, makes sense

warped crater
#

there's literally a boolean option type so

#

PR to dapi-docs

warped crater
# outer raven but what should I do about the undefined?
- export type AutocompleteOption = Pick<CommandInteractionOption, 'name' | 'type' | 'value' | 'focused'>;
+ export type AutocompleteOption = Pick<CommandInteractionOption, 'name' | 'type' | 'focused'> & { value: string | number };```
outer raven
#

ye thats what i was thinking

#

alright will PR

opaque vessel
#

Thank you

outer raven
warped crater
#

lgtm

opaque vessel
#

Fine to me too

wild flax
#

@outer raven ok hear me out

outer raven
#

hm

wild flax
#

Are you sure its safe to remove the cacheType?

#

I guess so

#

But

#

I think its be better if you still use Pick syntax

outer raven
#

oh

wild flax
#

And just overwrite it with & or something

outer raven
#

I didn't realize that but in this case I don't think it makes a difference

wild flax
#

like don't pick out certain things and then just do & { type: <type>, value: <stype> }

outer raven
#

that's only relevant for options with resolved properties like members or users

wild flax
#

might be better for not having all standalone types yknow

outer raven
#

if I keep Pick I'd only be picking name

#

I can change it if you want but it really doesn't make much of a difference

#

should I?

wild flax
#

That's true, but

#

What if they ever extend it in some way

#

I think itd be less of change for us then

outer raven
#

yeah fair

#

ill do that then

wild flax
#

coolio

#

ty

#

It also probably makes for better code consistency

#

And generally good practice

#

Also please, for the TSR rewrite, you wanted to have getters to builders right (for v14)?

wild flax
#

Is there any compromise we could find where you still somewhat get what you want to achieve, so you do your mutations with some sort of structure

#

but not builders directly

#

🤔

outer raven
#

well Siris suggested an update method a while back which would only modify the passed properties and leave the others untouched

wild flax
#

Would that be on builders or djs?

outer raven
#

on builders

wild flax
#

yeah I guess we could work with that

#

would call it patch instead of update, but sure

outer raven
#

but if we go with that idk if the set methods would continue to make sense

wild flax
#

they can call update

#

we can still expose them

outer raven
#

yeah true

wild flax
#

@tacit crypt does that fit into your RFC

#

I don't think that'd bastardise builders

outer raven
tacit crypt
#

I'd be fine with possibly having an updateX method if the need is there, but the set methods should not be removed at all

outer raven
#

yeah that sounds good

wild flax
#

updateX or update in general

#

because then wed just duplicate the set methods no?

#

lol

#

but without clearing

tacit crypt
#

well, update makes sense only for nested objects

outer raven
#

oh yeah you can just have 1 update method that works for all

tacit crypt
#

(consider: author, footer, icon)

#

So I'd say updateX for all nested objects only

outer raven
#

but wouldn't that be a lot of methods

tacit crypt
#

how so?

outer raven
#

well instead of 1 update method for the entire builder you'd be making 1 for each object

tacit crypt
#

updateAuthor/setAuthor
updateFooter/setFooter
updateImage/setImage
setURL
setColor
setDescription
...etc

outer raven
#

and for embeds for example that's a lot

tacit crypt
#

Embeds have only... 4? nested objects

wild flax
#

Yeah its not that much

#

Sure, if we duplicate all set methods

#

But thats not what vlad is saying

tacit crypt
#

I dunno, a global update method then brings the question for a global set method, which would really not help with the consistent interface argument of the RFC

wild flax
#

we could probably bring in those update methods before the RFC rewrite proposal

#

since theyd be minor

outer raven
tacit crypt
outer raven
#

im fine with both tbh

outer raven
#

@analog oyster @opaque vessel did yall delete your comments on the PR?

analog oyster
#

yeah, it doesnt really make a difference

outer raven
#

the name doesn't but the type kinda does

analog oyster
#

we were just talking about the focused prop

outer raven
#

ye ik

opaque vessel
#

Yeah it's fine to make that true 😅

outer raven
#

i pushed a commit to make it true

analog oyster
#

can you rename the type then

outer raven
#

no?

analog oyster
#

its kind of misleading, because not all autocomplete options have focused: true
the type is only being used in getFocused(), but still

#

if in the future that type is needed, it doesnt represent any autocomplete option

#

just focused ones

outer raven
#

all received autocomplete options do have focused set to true

#

when you receive an autocomplete interaction you only have 1 option which is the focused one

#

i just tested this btw

analog oyster
#

idk how else to put it, that type now represents focused autocomplete options

tacit crypt
#

You should be getting all provided options..

analog oyster
#

im not talking solely about autocomplete interactions

outer raven
tacit crypt
#

That's..not true, the API definitely gives all options

outer raven
#

vlad I just tested this

tacit crypt
#

If you have a user option then an autocompletable string option and you fill in the user one first, you'll get it (or SHOULD get it)

opaque vessel
#

API doesn't send any resolved data, just those in AutocompleteOption

tacit crypt
#

I recall this bc I also tested that Thonk

outer raven
#

ok lemme do a different test then

opaque vessel
#

That's why those getUser() etc. methods were removed from the typings on an autocomplete interaction, because there was nothing to resolve them against

tacit crypt
#

The fact its not resolved is one thing

#

you should still be getting the option

#

Even if not resolved

#

At least that's how I remember it MonkaW

opaque vessel
#

If you have an autocomplete option, for some reason, Discord just doesn't send anything else but it

#

It'll send the user id, sure, but not the user object

tacit crypt
#

So you do get the option

#

just not resolved

opaque vessel
#

Yeah

tacit crypt
#

Phew, thought that changed too

outer raven
#

so you get all the options you've filled up already and not any resolved data

opaque vessel
#

get('user_option').value would get the id but unfortunately no user object

outer raven
#

i was getting confused because I thought you were saying you would get options that weren't filled

#

also interesting how they send a number as a string 🤔

tacit crypt
#

That makes sense to a degree

outer raven
#

so would value always be a string?

tacit crypt
#

Since you can type anything in the autocomplete, for instance searching case numbers by reason

tacit crypt
#

Although it is definitely concerning then because even in -types it would be wrongly typed

outer raven
#

ok so ill rename it and make it always a string

#

do you have this interface in -types?

tacit crypt
#

It's probably only a string in autocomplete scenarios

outer raven
#

yeye

#

once you move to the next option and unfocus it it becomes a number

outer raven
#

alright hope thats the last commit to that PR

tacit crypt
#

Uhhh..yeah its in -types to a level... notLikeCrawl

opaque vessel
#

It just seems only floats are sent across as strings, right?

tacit crypt
#

If autocompletes are always sent as strings, I have some painful types to fix

opaque vessel
#

But doesn't that screenshot show a number or am I tripping

#

@outer raven poke poke^ x:

tacit crypt
#

thats not focused, Jira

#

We're talking about the focused property

opaque vessel
#

Oh

outer raven
#

Ye that type is only for focused options

#

@opaque vessel

opaque vessel
#

Omg lol

tacit crypt
#

........so autocompletes have the value as string...Le fuck

#

Should be easy to fix tho in -types

#

union all the things

analog oyster
#

focused autocompletes have value as string

#

right?

outer raven
#

yes

#

my code checks if an option's value is a number sometimes, I wonder how I never noticed that break

#

oh wait turns out it only checks if it's a string, thats funny

tacit crypt
#

I never noticed this because I never used autocomplete for numbers... yay we caught it

opaque vessel
#

Same... lol

unique axle
#

when they first got introduced i went firT on that, but it makes a ton of sense, bc it's essentially an enum/id you are selecting, with some verbose name as label

opaque vessel
#

I'm shocked lol

#

But sure

unique axle
#

yes? int ids exist, not everything is snowflakes, fam

#

there are multiple reasons why you wouldn't want to represent a... idk, job, in an RPG?... as a string, but rather with a job id

outer raven
#

but we were talking abt number autocomplete options

#

im confused

tacit crypt
#

Autocompletes can be used to also search

unique axle
#

yes, and numerical ids can make sense there, because you can assign a label to it

#

i could, for example, give every tag in /tags a number instead of using a string to identify it, making it a worthwhile use case for autocomplete numbers

opaque vessel
#

@outer raven can you update the AutocompleteOption JSDoc too?

#

Renaming it and removing the number type from the value

outer raven
#

done

#

should probably backport this to v13 right?

opaque vessel
#

I don't believe we are doing another 13.x

ruby terrace
outer raven
#

and there's 1 PR for v13

shell lance
#

That one would be a patch though, not minor version (if even merged)

wild flax
#

Don’t call me out like that

outer raven
#

but is this the last last one?

#

like qjuh said it could just be a patch

wild flax
#

Idk

#

We can do another 13 probably

#

The first time I said it was only because the release setup was a pain

#

But I fixed that

#

The 2nd time was because I thought v14 will be ready and TiV will be a pain to back port

#

Turns out neither happened

#

And TiV was easy

opaque vessel
#

Cool

#

There's already a 13.x pull request, so...

outer raven
#

then ill open the backport pr once that is merged

wild flax
#

You can open it now

#

And just fork or base it on that branch

#

So checkout that prs branch

#

Make a new branch from that

#

And work from there

#

¯_(ツ)_/¯

#

Just make sure it’s your fork

#

Not the persons fork

outer raven
#

i usually checkout main and just cherry-pick lol

#

which is why i wait for it to be merged

#

its quite easy

tender surge
#

Are typings missing here?

#

I don't see .setDefaultMemberPermissions / dm which is in the docs :/

#

Nvm seems like it was added yesterday so got to wait for a new release

real jetty
tender surge
#

Idk I just prefer to have regular objects to create commands, maybe I'm missing some type here

copper garden
#

You can see from the typings that it’s just a type, not a class or anything usable by js

tender surge
copper garden
tender surge
#

Well defaultPermissions is a property already

#

So there would be new defaultMember and defaultDMPermissions properties

copper garden
#

defaultMemberPermissions is alr on ApplicationCommandBase

tender surge
#

I don't see it 🤔

copper garden
#

Or let me check, I realized ur showing ur own typing

tender surge
#

Yup

#

If I can add some reference to anything that has it to make it work it's all good, but currently I see no way of achieving this

copper garden
#

It’s on v14 dev

tender surge
#

Okay then I did see it correctly, ty for checking 😩

copper garden
#

No backports to v13 atm

tender surge
#

I guess I can use the dev version since this bot isn't live

stray delta
void rivet
#

try this out

class BaseClass {
    /**
     * Send message
     */
    send() {}
    /**
     * Fetch message
     */
    fetchMessage() {}
    /**
     * Edit message
     */
    editMessage() {}
}

class ExtendedClass extends BaseClass {
    /**
     * Sends a message with this webhook.
     * @param {string|MessagePayload|InteractionReplyOptions} options The content for the reply
     * @returns {Promise<Message>}
     */

    /**
     * Gets a message that was sent by this webhook.
     * @param {Snowflake|'@original'} message The id of the message to fetch
     * @returns {Promise<Message>} Returns the message sent by this webhook
     */

    /**
     * Edits a message that was sent by this webhook.
     * @param {MessageResolvable|'@original'} message The message to edit
     * @param {string|MessagePayload|WebhookEditMessageOptions} options The options to provide
     * @returns {Promise<Message>} Returns the message edited by this webhook
     */
    send() {}
    fetchMessage() {}
    editMessage() {}
}
```Hover above send then fetchMessage
#

hopefully this clears the confusion
i think i know what you mean by seeing something similar, you probably saw some seemingly out of place jsdocs and misunderstood what they were doing
i'll see if i can get an actual example

opaque vessel
#

@outer raven and anyone else, we'll make a 13.8.1 release (patch) so if there's any other fixes you want making to there, can do

outer raven
vernal rose
golden mortar
#

its not too late to just move to json. builders are way too complicated

copper laurel
#

I personally agree. But we still support JSON everywhere anyway (it's literally what builders build for you) so this is just an unhelpful snide remark and not constructive discussion at all

#

Nobody is making you use builders

golden mortar
#

But we still support JSON everywhere anyway (it's literally what builders build for you)
that's what they should be doing (like Embed in v13), but they also do validation which is part of the "too complicated" remark.
Nobody is making you use builders
I'm not, not sure what that has to do with anything lol. I doubt any of the maintainers (people making all of the massive changes) use builders' structures either which is definitely another problem (feel free to correct me if im wrong here)

#

I also agreed with just about everything u said on the rfc, just haven't posted on it

copper laurel
#

This message before yours was about disabling the validation on a single unified builder structure rather than having the Unsafe* separation.

#

As for usage of builder by maintainers I don't know enough to comment - I don't use builders myself

#

The fact that they validate the input isn't a problem for me, and for what it's worth I think the slash command builders are excellent. Immutability lends itself well to that scenario. It's all the others that are the problem 😄

dawn merlin
golden mortar
copper laurel
dawn merlin
#

Personally it’s out of habit

#

I don’t think one is objectively easier than the other though

#

As for the immutability that’s less of a builders issue and more of djs one. Djs controls the cache and decides how components are cached within messages

copper laurel
#

Im not asking to mutate cache

dawn merlin
#

Even if builders wasn’t a separate package I still would’ve made that PR

#

Then what are you asking to do?

golden mortar
#

the idea of having to convert a component to json to convert it to a mutable component seems very contrived to me personally.

#

or even if you don't convert it to json manually it still gets converted to json

dawn merlin
#

A component or a component builder?

golden mortar
#

from monbrey's example in the rfc

ButtonComponent.from(theData).setDisabled()
dawn merlin
#

I need more context here, where is theData from

golden mortar
#

I don't think it really matters tbh (it's just really complicated for changing a property on an object). You could replace that line with

theData.disabled = true

if you were using just json objects
however I do have an example:

In one of my bot's commands, it sends a message (using interaction.editReply, which apparently always sends a Message object now?) and after a collector ran and the message has been updated (dynamically adding/removing/modifying components), I want to resend its components but disable them so they can't be re-used after the command is over.

message.components returns an ActionRow structure where I can access components and whatnot, but I can't edit them. I could recreate the component using ActionRowBuilder.from, but the data would already be converted to json regardless and I could just as easily modify it directly. I think the example in the pics are equal (taking the first component of a message, setting every subcomponent to disabled) and as you can see the 2nd one is quite a bit more complicated - while also getting "worse" typings.

copper laurel
#

If you have 5x5 grid of buttons and you want to disable the one right in the centre, how would you do that using builders?

copper laurel
#

e.g. if r.data is private, you're shit outta luck

golden mortar
#

apparently the .data isn't private, the example was done in ts (modifying my actual code). However idk the design of builders and it might be against every design input lol

dawn merlin
# copper laurel If you have 5x5 grid of buttons and you want to disable the one right in the cen...

Factory functions; if you’re generating 25 buttons I doubt you’re making them all statically. Make a function that takes state as an input (Map) and returns component as an output. When you receive a component update the map and call the same factory again. Components shouldn’t be responsible for encoding state. An array of action rows isn’t a replacement for map-like structure. This is true for both json and builders

copper laurel
#

That sounds horribly inefficient to have to use the factory over and over again

#

I already have a set of 25 validated buttons, why cant they be reused

#

Maybe to give a real world example, I've seen implementations of tic-tac-toe with buttons where the label gets updated with an X or O based on position

dawn merlin
copper laurel
#

Well no, I wouldnt

dawn merlin
#

Then how can you be sure state doesn’t carry over between interactions between different users?

copper laurel
#

I'm not understanding the question

dawn merlin
#

I’m saying you always have to reinit state whenever a new interaction comes in, or else you end up using the same state for all users invoking a given interaction

copper laurel
#

Why would the state have changed

dawn merlin
#

If two users are playing tic tac toe I can’t allow them to use the same components in the same state

#

Two separate games*

copper laurel
#

Would those two states not be in separate scopes of execution?

dawn merlin
#

Sure but they both need to created separately, right?

copper laurel
#

Once

#

Not on every turn

dawn merlin
#

But you can’t modify cache in place, you always need to recreate the component with .from

copper laurel
#

Yeah if you use builders

dawn merlin
#

Well the api returns immutable structures so it would be a similar story with json

copper laurel
#

But you'd already have your JSON that you used to send them in the first place, and it's mutable. I don't care what the API gave me

#

Hell you could even make that JSON using builders if you really wanted to, and then edit an individual property in it as needed

dawn merlin
#

Yeah the json still needs to be created every time, other than validation you’re not really saving much construction cost.

ruby terrace
copper laurel
#

No I dont

dawn merlin
#

ckohen who was that directed towards?

ruby terrace
#

you

copper laurel
#

...no it doesn't. What am I not explaining properly.

const ttt = [array of rows of buttons in JSON];
const game = await interaction.reply({ components: [ttt] });
const collector = game.createMessageComponentCollector(options);
collector.on('collect', b => {
  // b.customId shows that the middle button was clicked
  ttt[1].components[1].label = "❌";
  ttt[1].components[1].disabled = true;
  b.update({ components: [ttt] });
});```
#

I do not need to recreate that JSON

#

It exists in a scope where its mutable per event received by the collector, but out of scope of any other interactions that may have started games

dawn merlin
#

If you know the exact component index why not keep a reference to the builder variable and just mutate that then?

copper laurel
#

Because isnt it supposed to be private?

#

Hidden away behind builder methods?

#

And if its isnt whats the point of the builder?

dawn merlin
#

No if you know what component in the actionrow changes every single time, why not just keep a reference to the builder?

ruby terrace
#

mutating specific field indexes is incredibly difficult with builders

dawn merlin
copper laurel
#

And modify it how? spliceComponents?

dawn merlin
#

no the setters

#

It’s a reference to a builder

copper laurel
#

so RowBuilder.components[1].setDisabled()

#

I thought they were also private

#

Or .data.components I guess?

#

We're back to data being a public property again then

dawn merlin
#

You already know what component 1 is beforehand. Keep a reference to that component builder. Place that reference into the action row builder. When the collector is invoked use the cached component reference and call .setDisabled.

copper laurel
#

That would currently be possible, how would that still work if it changes to the row.addButton(button => style to align with slash commands?

dawn merlin
#

I have no clue

copper laurel
#

I realise now we may have been approaching this with entirely different states of builders in mind

#

Apologies 😄

dawn merlin
#

all good

ruby terrace
#

you could store a reference to that too, but you're storing so many references now

#

when maybe only one of them needs to be updated

dawn merlin
#

customid -> component reference

dawn merlin
ruby terrace
#

*when the GC works

dawn merlin
#

I don’t see why it wouldn’t here

#

It’s scoped to anything in the interaction block. That’s like saying you shouldn’t allocate anything in an interaction event handler bc GC may not work(?)

#

If it didn’t work memory leaks galore

ruby terrace
#

naw its just slow, in my use cases its not a problem

dawn merlin
#

Deallocing a tiny map (of mapped references) shouldn’t be slow enough for like 98% of people to notice. There’s probably structures being dealloced that take more cpu time

ruby terrace
#

Let me give you an example for an embed quickly (doesn't apply currently because the builder doesn't follow the same structure)

#
const fields: EmbedFieldBuilder[] = []
const embed = new EmbedBuilder().setTitle('An embed');

for (let i = 0; i < 15; i++) {
  embed.addField(field => {
    fields.push(field);
    field.setName('Name').setValue(`Field ${i}`);
  }
}

// Somewhere else, after getting an event
fields[someIndexFromEvent].setName('Name (Winner)');

vs

const embed: APIEmbed = {
  title: 'An embed',
  fields: [],
}

for (let i = 0; i < 15; i++) {
  embed.fields.push({ name: 'Name', value: `Field ${i}` })
}

// Somewhere else, after getting an event
embed.fields[someIndexFromEvent].name += ' (Winner)';
#

In example two, I do not need to lookup the current value of the name in order to append to it, only have the overhead of storing the json object (not classes each containing their own json object), and its easier to index into

dawn merlin
#

this is quite easy to solve store the field builders in an array, set the fields to that array. On the event being recieved go the index in the cached array and change the title.

ruby terrace
#

that's basically identical to what I just did

#

heck I could even use the toJSON() output from the builder in 1 and use the same last line from 2, but then I lose the validation

dawn merlin
#

In your example you don’t assign the fields to the embed directly you add them all one by one

ruby terrace
#

it'd still be nearly identical

#

and that's not the point

dawn merlin
#

I don’t see the issue, you’ll always know the name(s) beforehand since you create the array with said names attached to each element. And it’s logical to assume these “names” would be in the same indices as the as the field builder.

ruby terrace
#

but that's exactly why its frustrating for people

another frustrating thing:
now imagine you're doing this over time and not in the same scope. Instead of storing just an embed object / builder, i have to pass around all these extra things to wherever I'm storing them

dawn merlin
#

Alternatively you can look up the index off the received message embed and look for the already existing name string

dawn merlin
ruby terrace
#

i'm not storing it in a message component, i'm storing it in a Map (Map<number, APIEmbed> currently), but your way would suggest using that same map and shoving everything that I might potentially need into an object that contains references to every nested builder in addition to the top level one

dawn merlin
#

Huh? In the example you just need the array of field builders that’s it

ruby terrace
#

I need the embed itself too

dawn merlin
#

why?

ruby terrace
#

to use it in edit or send or whatever

dawn merlin
#

they’re references you change the field in one place they change anywhere they’re referenced

ruby terrace
#

I know

dawn merlin
#

you don’t need the embed

ruby terrace
#

then how do I resend it

dawn merlin
#

you edit the field and resend

ruby terrace
#

but I don't have a reference to the embed

dawn merlin
#

Exactly you don’t need one

#

The embed you started with is referencing the field you’re editing

#

You just need the field

ruby terrace
#

but if I only store the fields in that map, I don't have the reference to the original embed anymore

dawn merlin
#

It still will be edited when it’s resent bc the embed you lost the reference to is still referring to the field you’re editing

ruby terrace
#

then how does .edit() know what embed I want to send

#

remember, we're in a completely separate block scope here, that's the point of using the map, to transport these things between scopes over time

dawn merlin
#

When edit is called you need the embed itself regardless if you use json or a builder. I’m saying for editing a field locally it’s not necessary just like it wouldn’t necessary in json

#

if you’re using json an lose a reference to an embed then obviously you can’t send it

ruby terrace
#

right, but the map is just storing the entire embed, and map.get(id).fields[x] etc... works great

dawn merlin
#

why is a map being used instead of an array of fields?

ruby terrace
#

its a map of embeds

dawn merlin
#

why embeds?

ruby terrace
#

so you've lost the context for this conversation?

dawn merlin
#

In the example there’s only one embed

ruby terrace
#

now imagine you're doing this over time and not in the same scope. Instead of storing just an embed object / builder, i have to pass around all these extra things to wherever I'm storing them

#

so over time we have multiple

#

lets just say the map is on globalThis for this example

dawn merlin
#

In this map what are you trying to edit on each embed?

ruby terrace
#

unknown, may be every field, may be a single field, may be add a field

#

I honestly don't know how we could solve this in builders without exposing data which defeats the purpose, maybe getters for only things that can have nested builders

dawn merlin
#

ok the solution of keeping a reference to only the fields still works here

#

You edit the fields in place

ruby terrace
#

here, simplified so og scope: makes embed and fields, sends, separate scope: edits fields then edits message

dawn merlin
#

Is this separate scope within the og scope

ruby terrace
#

no

#

same event handler, different event

#

both have ways to access the map

dawn merlin
#

Ok then this is just a factory function problem. Have a function that takes abstract state and outputs an embed.

#

This function can even take in the recieved embed as input to represent updated state

ruby terrace
#

Let me try to make the point clear: yes, we can find ways to do what we want with builders, and the best part is validation. However, doing so seems arbitrarily hard sometimes, attempting to find workarounds for problems we encounter. Unfortunately, discovering and implementing these workarounds is trumped by the ease of simply using JSON instead. I.e. storing all the nested builders works, great. I didn't think of doing that because its not exactly intuitive, and it still seems like I lose flexibility with it, so give up and use JSON. Thought process goes: I lost runtime validation, oh well, haven't had issues with it before.

dawn merlin
#

Json has always been more flexible even with v13 builders, and it always will be.

ruby terrace
#

The goal I imagine would be to make it feel easy to use builders over JSON

dawn merlin
#

That’s why json isn’t validated and builders are. It’s also why you can pass in colors and emoji as just strings in builders and you can’t do that with pure json. People value certain things over other things and builders may be more useful to them. Others may find json much more useful.

#

Personally speaking I don’t think the goal of builders was to obsolete the use of JSON

ruby terrace
#

But if i'm using builders, I don't feel like I should have incentive to stop using it ever

#

whereas currently when I start using it took all of 3 minutes to decide to stop

dawn merlin
#

Let’s reverse that statement, if I’m using json I don’t feel like I should have incentive to stop using it. And to be clear I feel like giving up on something after a mere three minutes doesn’t really show an honest effort to adapt to changes.

ruby terrace
dawn merlin
#

Some people think the the more raw nature of json makes them harder to use

#

Anyways it’s 2:20am and I need to get up at 8am so gn

ruby terrace
leaden obsidian
#

@wild flax @tacit crypt Hi I am Voxelli @fervent walrus [github:legendhimslef] using this id cuz older one has some issues,
I think we need to have 13.8.1 as soon as possible as the code on 13.8.0 resets sessionId on close which causes new identifies. This has been patched in my latest pr. || sorry for ping it was kinda urgent I think cuz there is a chance that this will cause some users to exhaust all their login quota ie 1000 per day||

#

Ill get the backport ready for main [main does not have any sessionId issues]

leaden obsidian
#

I think this was mainly affecting bots with 20-30+ shards on 13.8.0.

tight crag
#

Every 20-40 minutes some shard is reconnecting with new session

leaden obsidian
tight crag
leaden obsidian
tight crag
#

No

tight crag
#

@leaden obsidian 👀

leaden obsidian
#

or the one which got merged with 13.8.0

tight crag
leaden obsidian
tight crag
#

Thank you

leaden obsidian
#

idk why I never noticed this until now. My bot with 34 shards never ran out of logins per day maybe cuz of traditional sharding? but for internal sharding peeps it caused some reconnect issues [only for huge bots]

tight crag
oak quail
#

looks like d.js is adding webhooks to the user cache now; is that intended?

dawn merlin
#

It was, but there’s a PR to revert it now

vernal rose
#

@tacit crypt u said enableValidators should set setValidationEnabled to all the predicate (if I've understood correctly then u mean import all the assertion predicates in validation file and use setValidationEnabled on them right?) and not just before parsing but how that'll work? https://github.com/sapphiredev/shapeshift/blob/a23d15f533a234a59af54a9ed60bec778f069af8/src/validators/BaseValidator.ts#L80 here everytime we run setValidationEnabled, it makes a clone so if i add setValidationEnabled(false) on a predicate inside of enableValidators, it won't change the already present predicate

grizzled elk
#

I've been developing a library ontop of DJS and I just wanna say great job to everyone who works on it.

#

It has been very easy to work ontop of. With such a big featureset, that's not really an easy thing to pull.

#

pat

wild flax
#

Link?

#

Yes you are allowed to