#archive-library-discussion
25085 messages · Page 5 of 26
Oh I understand, breaking changes comes into new releases ?
This will need #4879 before it lands.
which is the switch to gateway v8
which is semver major
=> slash commands will land after 13.0.0
:oops:
hadn't realized interactions were v8
for reference see: https://semver.org/
breaking changes need a semver major - format being MAJOR.MINOR.PATCH
current stable is 12.5.1, meaning a breaking change will happen with 13.0.0
the next breaking change 14.0.0 and so on, where as minor releases are new features and patch are bug fixes or internal improvements
Mh I see, I was thinking that you have to change the MAJOR version when there is a big feature that comes
Standard reminder that -next is not the next major release either way
so there is no option for INTERACTION_CREATE
That's actively being developed, please check the pull requests (you can also get the raw event)
i see
is raw event available?
yes, ask in #archive-djs-v12-deprecated for how to get raw events
Please don't, we do not support the raw event, it's private for a reason
@raven juniper client.ws.on works and is public
i see nothing about it on the client.ws docs but i'll take your word for it, i don't mess too much with that stuff, i just know it's a pain and people looking for support aren't likely gonna get any because not many people know it
we don't document what events we emit on client.ws for..obv reasons
But, any packet that has a t will get emitted
WebSocketManager extends EventEmitter
The WebSocket manager for this client.
This class forwards raw dispatch events, read more about it here https://discord.com/developers/docs/topics/gateway
Is .tern-profect still needed?
Should Client#token really be instantiating to process.env.DISCORD_TOKEN if it exists?
The behavior seems really odd
what's wrong with it?
Nothing in particular
just wondering why it was added
it seems like it would only be useful for env vars but nothing really else
this way you don't have to "store" token in your code
it's also used by the sharding manager to pass the token to the shards
and considering that there are million other ways to populate process.env than dotenv, you can do it from outside of your bot code or even node
ah k
makes sense
Are there any plans to encorporate the pending property on a guildmember? Ref: https://discord.com/developers/docs/resources/guild#guild-member-object
yes, search GH for PR, if none: make one
Make one, got it
haven't done step 1 yet, so that might need to happen before 
there is one nevermind
is there support for the new /command system?
oh thanks
Nico beat me to it 👀
Care to link me? I'm either dumb or blind I guess.
Oh nice, already a PR
I assume this will arrive in v13 as well?
I don't see why it wouldn't come in v12, it's not a breaking change and the PR doesn't specify whether only the v8 api would have it
I'm not sure but I think it makes more sense to have an event for that maybe GuildMemberAccept it emit when the member accepts the rules so we can do something like sending a welcome message or giving a role
we cannot really implement something custom if the API does not support natively (which makes it a way unreliable), so that is upto them, then surely.
it's semver minor meaning it could come to v12, however, i do not believe there will be another release before v13 (at this time at least)
This is correct and it needs API v8 so it’s a v13 only
How does it require v8 though?
it doesnt
I have not touched v6 in a long time but gus mentioned the v8 PR in his
Do registering commands / the gateway event exist in v6?
oh, we were talking about the guildMember#pending property. As far as v6 for interactions, I've heard they work just fine, but we should be on v8 at that point anyways
Right. I was looking at the wrong PR then.
Either way, very slim chance this will be released in the 12 cycle, as semver:major prs already landed in master
But what about userUpdate? Referring to this message that claims userUpdate is merely an artificial event emitted by djs <#archive-library-discussion message>. If we can have artificial events like user update why not a guildMemberAccept?
why? should be the question, rather than "why not"
it emits guildMemberUpdate, you check #pending on old and new
if the end user wants to make that its own event they are free to use the node vent API to emit it, but i don't see any benefit in doing it on the library level
There's also been a lot of push to make that event a native API event, but as long as we get a difference in pending state, then it shouldn't matter, that's an easy check to make.
and that push is just as nonsensical from discords perspective, it emits an event, that single check should not warrant it being its own event
- nvm, intents have happened, people want to operate without cache
ofc, if it becomes its own gateway event it will get its own Client event in discord.js - as it is GUILD_MEMBER_UPDATE currently however at the present time that makes no sense on the library level
I doubt it will become its own event at this point, supposedly we only get the pending parameter (set false) on the GUILD_MEMBER_UPDATE event after someone finishes screening. That should be enough for people without cache too.
agreeing Souji and ckohen on that, I guess must be fully enough to make a (single) check against the .pending-property (as GUILD_MEMBER_UPATE already emits for that specific change), and except if you're messing with partials.
https://github.com/discordjs/discord.js/blob/master/src/structures/IntegrationApplication.js#L13 is that a property the library adds to the data object somewhere? https://discord.com/developers/docs/topics/oauth2#application-object doesn't seem to document it
thats an IntegrationApplication (https://discord.com/developers/docs/resources/guild#integration-application-object)
oops, didn't notice that integration applications have their own part in the docs
thanks
Can I ask here if the Collections utility is still maintained or would that be off-topic?
it is maintained
I was asking some questions in the Discord Development server, and someone mentioned that if discord.js hits a rate limit, it waits until the limit expires and then tries the call again (#697489244649816084 message). Is that accurate? I feel that when I call a method that might be rate limited, I should be able to pass in options to tell it whether I want it to retry and/or whether I want it to throw an error. At the very least, it would help in debugging. But ideally if the bot can't do something right now, I'd like to be able to act on that. My bot could say something like, channel.send('Sorry! I've been doing that too fast, and I'm not allowed to right now. Please try again later.');
The behavior you are describing is correct.
Something like an option to limit retries that are longer than x or the like have been brought up, but nothing really has been done in that regard so far.
Oh, interesting. I missed that. So, something like setTopic - I'm limited to 2 every 10 minutes. Does this fire when I've done the second one, or when I attempt the third one?
So discord.js will still make that attempt later, right?
Is there any way to stop it from re-trying that request?
You would get a debug log there, rate limit only emits when the request is preemptively throttled. (That is indeed a bit weird)
No, there is currently no way to cancel a request.
Are there any ongoing discussions about this topic? I'd be willing to take a stab at something and make a PR, but I'd totally welcome some guidance onto what the best way to handle all of this is.
Option 1: A map of known rate limits. We could fire a rateLimitWarning based on a map of known values: If you try that again in the next X seconds, it will be rate limited.
Option 2: Some hook on the current rateLimit event that does the current behavior by default, but the developer can do something with the event to cancel the request if required.
Option 3: Pass options into anything that might get rate limited to tell it what to do.
Out of these 3, it seems Option 2 is best to me. But maybe there are other options I haven't thought of.
I am not aware of any discussions currently (or recently) about that. (I am pretty sure there was something about that, but I can't find anything at the moment.)
1 is a no, since Discord might change limits at any point, and is generally not happy about hard coded limits.
3 is possible, but feels like it could become a hassle since everything is subject to be rate limited.
2 indeed looks like something that could be done, although I'm not too sure how it would work exactly.
Some possible naive solution could be to add a function to the object that, when called, cancels the request (causing the returned promise to reject with some error).
My initial idea was to be able to configure a static limit for rate limits as client options, but that might be a bit too broad, while yours would allow better control about when to (not) wait.
So - I haven't FULLY read the code yet. Just given it a quick glance. Requests go into a queue, right? If we attached a UID to each request, we could pass back the UID in the rateLimit event. Then we could provide a method to remove an event in the queue by passing in a UID.
They go into a queue, one per route.
Okay. So if we have a method called something like cancelRequest(route, uid), that might work.
Find the queue for the route and in there, find the request with uid...
And although a bit confusing given the rateLimitInfo.method there, it might also be interesting to pass back the name of the method that was called. For example, rateLimitInfo.callingMethod: 'channel.setTopic' or something like that.
Unless that's information that's in the route already. I'm not familiar with how the routes are named in the API.
I guess my only remaining question is - if I tackle something like this, how do I ensure I'm doing it in a way that will be accepted in a PR? I don't want to do the work, and then have someone say, "no, we're not implementing this." That's the only reason for all of this discussion/questions. So what do I need to do/to whom do I need to speak, to make sure that the spec work I'm doing describes work that will be accepted?
Somewhat, I don't think there are too many, if any, not-helper functions sharing the same route.
What public-facing-method caused the request is currently not known to the request handler.
That is indeed a good and reasonable question, which I do not really have an answer to 
I'd be +1 on this feature, but think it could be troublesome to actually cancel a request that currently waits for a rate limit to expire (as that's just a promisified setTimeout, and polling some cancel flag does not feel too right?).
But I do not really have another idea about how that would work.
This'll be my last post. Please @ me if you reply so I can check it later. If we put the setTimeouts into an object with that UID I was talking about as the key, then we could do clearTimeout(queue[uid]). Maybe. Anyway, I'm off. Merry Christmas. Thanks for the chat. Is it correct that I'll need to make an Issue describing my spec ideas and wait for a +1 from you and/or someone else to know it will be accepted? any clarification on how I can only do work after knowing it'll be accepted is appreciated 🙂
im refactoring usages of GuildChannel#permissionsFor to handle there being no permissions returned, but in the getters should i just return null here or default to false?
null feels like better option but i just want to be sure
There's a difference between false and "we don't know", right?
yeah
i ask also because
GuildChannel#viewable just returns false
if there are no permissions
but all the other getters just error
why not also take GuildChannel#viewable under consideration to be removed (relative to all other removals for v13)? I think it has been discussed once
<#archive-library-discussion message>
I believe what nico is referring to is removing stuff like GuildChannel#viewable, the basic permission checks that the user can very easily implement
agreed there, users must be able to do basic logical checks 🤔
hey uh guys, i heard you guys are removing the like <message>.delete({timeout:500}) functionality in v13, and im a bit confused as to why?
i dont see any downsides personally to keeping it, and it really helps keep code clean
rather than having a lot of settimeouts which makes code kinda messy
if someone has a moment can they please like gimme the reasoning behind this? thanks!
it should never have existed in the first place.
no other structure has a native delay on delete, why should message have one? this is nothing the API actually supports but just a timeout wrapper, which the dev can do themselves to the same effect through Client#setTimeout
it also forces you to think about how to handle deleting messages after a time (such as checking if it is actually still deletable)
yeah, personally I understand how like no other wrapper has a native delay for deleting and stuff, but since it's already like there, and it doesn't exactly have any downsides, I'm not getting like why you guys are removing it
(sorry if i seem pushy, im just genuinely kinda confused)
this was the last push, since there is actually a lot of things you need to take care of which immensely complicates the whole endeavour
if you miss the functionality you can always add it back by extending the structure yourself
oh, oof, i guess that kinda makes sense, Personally I still feel like the amount of code a lot of devs will have to re-write isnt worth like removing functionality, since theres other options if you dont wanna use it, but I guess that like reasoning kinda makes sense, so thanks!
we generally are moving forward with removing inconsistent and unnecessary "convenience" methods, since they have and still do cause more pain than they relieve
i guess this is also a good idea, thanks!
wait if you have some spare time, can you like help me understand how they cause pain? im kinda like not getting it, srry
amount of code a lot of devs will have to re-write isnt worth like removing functionality,
this is not a consideration we make for major version updates.
we are moving forward with what's the more consistent, coherent and ultimately hopefully semi-straightforward API
ohhh kk gotchu, ty!! 👍
Hey there. I don't think my question is 100% related to Djs, but I'm wondering how events work. (ex. client.on('event', callback) in d.js). I first thought that the Discord servers were sending a request to the local machine to trigger an event, but it seems very unlikely. How is the message event triggered for example? Is it some kind of infinite loop that keeps asking for updates over HTTP? (please ping to answer)
updates aren't sent over http, your client opens a websocket connection to the discord gateway where it receives events on client.ws and forwards them to the user
Oh, ok! It makes sense. Thanks
Could the member who deleted /created a Channel be added to channelDelete and channelCreate? It could be pretty useful to a lot of things.
we can only provide information discord provides, so that's a "nope"
"who" did something is always accessible through audit logs, not the general event that emits when it happens
Sad that discord does not provide that directly in the event
Alternatively, if you're not using Node.js v15, you can use const sleep = promisify(setTimeout);, then do await sleep(1500); to delay the execution of the following code by 1500 milliseconds, that's a lot cleaner than making callbacks within callbacks: https://nodejs.org/dist/latest-v15.x/docs/api/util.html#util_util_promisify_original
oh yeah wait both of these options help a lot! tysm! 
Should i pull request directly to the master branch or PR a new one? If creating a new one, how do i name it?
You should never commit directly to master
And whatever seems most logical to you
Do i name branch using my github nick and PR to djs repo then?
it doesn't really matter. you're going to create a branch on your fork, which would just get merged into one of branches at the upstream (or closed)
Not sure if this is the right channel but what is message.nonce even useful for? I was just reading docs and couldn't really see a use for it other than maybe checking if you already fetched the message?
used for validating a message was sent
https://discord.com/developers/docs/resources/channel#message-object
It's something you send that you can use to verify when you get the response back, e.g. if you send a message with nonce foo bar, you'll get a response that will be a message with nonce foo bar.
However, all other clients (and even you when fetching the message) won't get said nonce again. Think of it as an integrity check. @grizzled rover
I guess this got purged on accident:
The current behavior of the USER partial only affects reaction events and typingStart. Since userUpdate is an internally emitted event through GUILD_MEMBER_UPDATE in most instances, it makes me question whether userUpdate should be emitted for an uncached user. Right now it does not, and other Partial types behavior seem to suggest that it would. Does anyone have any insight into whether this was just an oversight or if its intended.
I definitely see how it could be intended since most GUILD_MEMBER_UPDATE events have nothing to do with a user update, and this would always emit userUpdate if the member was uncached, even when only member parameters have changed.
i'm currently questioning if userUpdate should be tweaked at all, or if it should just be emitted for current user changes, as the API emits it
Yeah, I was highly considering suggesting just to remove the external handles into userUpdate completely
i'd personally suggest that, i don't think so there is any use to emit it artificially other than convenience, which rather makes it inconsistent and harder to manage on the library level 🤔
And to further that point, the event is probably significantly more confusing for users now that at least one of the privileged intents are required to get the event. I think this would go hand in hand with many of the other changes for v13 that aim to emulate the API more directly.
I have a question, why on GitHub can't we see the versions prior to v5, and where can I find these ?
npm install discord.js@version
all versions before v11 are deprecated and probably dont work / are very broken
I know
but just for seeing the code
why aren't the v11 versions marked as deprecated in npm?
Probably an oversight
But yeah, we should eventually mark v11 versions as deprecated, as they'll stop working next year
Would we prefer having separate prs for removing all the unnecessary getters (like viewable and other dumb permission checks) or is it alright to have one collective pr for the removal of all unnecessary getters
and hearts to @old kelp for the reminder abt this 
don't understand why anybody would want to get rid of those
i think the point is removing "unnecessary and inconsistent convenience methods" as per <#archive-library-discussion message>, which we are already moving forward with
@unique axle was t:caching label intentional for https://github.com/discordjs/discord.js/pull/5152 🤔
it's not rest, it's not gateway, i thiiiink caching can be interpreted as "methods that don't do any calls outside and don't interact with discord in any way"
could be that my interpretation of that label is wrong tho 
nvm, it's utility, i'm a doofus
ah, right, thanks 
so cough cough #archive-library-discussion message
don't see how the permission getters fit into that description
Some of them are simple permission checks that the user can do on their own, unneccessary for the lib to provide methods for something they can do on their own imo. It also feels like a bit of pollution
This has been a debated topic for a while but people generally lean towards removal, for a cleaner library.
Having said that, I think the checks we're removing should be "ported" over to a guide page - there are other ways to support good practices.
Agreed. One other thing I'd like to ask, if we have other methods that depend on the getter, should we leave it?
I don't think there's any good reason to remove the permission getters, specifically.
- They add almost no additional overhead to the library in terms of maintenance
- The tiny bit of overhead they do add (making sure the permission checks change to match up with Discord's behavioural changes) aids in making the users' lives much easier, ensuring they don't have to go through and make the same updates themselves
- They are substantially cleaner for users of the library vs. the alternative
- They give a simple, descriptive name for what a bunch of otherwise arbitrary permission checks are accomplishing
- They often build upon each other (see GuildMember#manageable -> kickable/bannable)
Seems foolish to remove these widely-used getters that aid in producing much cleaner code on the users' end in the pursuit of a "cleaner" library (they're not even messy, inconsistent, or obtrusive in any way that I can think of internally)
All you would be accomplishing by removing them is making an extremely common task much less convenient/clean, there's not even a downside to them existing afaik
what could perhaps be better is making them more consistent, as the above complains about them not being so
Don't think they were called inconsistent. I believe that was directed at the weird message delete timeout functionality that nothing else shared
In my PR I outline that getters that are used internally (see point 5 of gawds message) wouldn’t be touched
Sounds like you'd be introducing more inconsistency by removing the ones that aren't, then
Because then you have some convenient permission getters with much smaller coverage vs. them generally being available on everything where relevant
In fact, I think these permission-related helpers should be expanded further. Any object -> action relationship should be covered, ideally. Additionally, the comparison should be able to made between any two arbitrary objects, not just with the client user/member (i.e. a GuildMember#canBan(GuildMember) method or GuildMember#canView(GuildChannel))
just to clarify: you are suggesting we should essentially have a permission getter per flag on the member as well as a getter per overwritable flag per channel type
additionally relationship methods as well as - possibly the reverse GuildMember#canView(GuildChannel) - GuildChannel#canBeViewedBy(GuildMember)
the reverse, no, not really
and not every flag, just actionable items
maybe, actually. i can see the argument for it but i feel like it makes more sense to always start from the object that is performing the action
So ur saying we'd add fail-guards for permission errors to methods like TextChannel#send?
no
i do actually like the idea of this, you see a lot of member-to-member checks in kick/ban/other mod actions, and it feels like the same as Role#comparePositionTo
should it really be the responsibility of the library to do simple permission checks
permission checks are rarely simple
Why is Role.comparePositions static method still there? I thought the raw position moved to Role#rawPosition?
Or at least why is it still using Role#position
I agree with that, if you take a look at some of those permission checks you are removing with your PR Nico, there's actually around 5 checks going on for each one (aside from editable). Because of the slightly weird way discord handles permissions, some of the steps of these are likely to get overlooked by many people if they are implementing it themselves.
Agreed. I think it is absolutely the responsibility of the library to abstract the [often obscure to those not intimately familiar with discord/its API] requirements behind whether you can do something to an object or not
Hm, then should the PR be reduced to only getters like message#editable?
Personally, I don't really see any reason to remove that one. Just because it's much simpler than the others doesn't mean it can't change in the future. Plus, that would only bring inconsistency, IMO
That one is kind of unique in that it's not tied directly to a permission currently
I feel like that may be necessary for an edge case that is coming soon (but this particular one puts a lot extra on the library): interaction responses are from the same user id, but aren't guaranteed to be editable. E.g. once the token expires, and those must be edited via webhook, not the same general edit method
some of them like voicechannel#speakable and the likes are just wrappers for permissionsFor, which would fall under my meaning
I think that wrapper methods like that were the original aim. This becomes a question of whether those actually want to be removed, as that encompasses all of the basic *.edit() wrappers as well. IIRC, that is a desired end goal, but needed further discussion.
I agree with gawd here, I don't really see a benefit in removing these, it just adds more work for bot devs
I do support changing things which would have an actual improvement, like, iirc someone said changing channel/message type to numbers saves a lot of ram? although they were numbers in early v12 dev iirc; that has an improvement and doesn't really have a disadvantage other than having to change code
but removing these methods seems to have disadvantages with no advantages other than them just not existing
I support those changes as well, those type from string to numbers changes would also align with the removal of strings for permission flags
That was me, and yeah, I'll be working on that once #5132 is finished
Probably before, I want to evaluate the impact the refactor will have to other PRs (merge conflicts mostly)
#5022 definitely needs to be merged before I can do that
Just pending review from Space
So then is the decision to keep all the getters including ones like message#editable and voicechannel#speakable?
is the reply-prefix branch gonna be deleted?
its just been sitting there for months lol
the native replies are going to replies discord.js's reply, making reply-prefix useless
Would it be out of scope for the library to include a few handy regexes, like the elusive invite link regex
that specifically you can grab from resolveInviteCode
?docs DataResolver.resolveInviteCode()
@snow crypt You can apply this to a whole message and get an invite code?
yes
you can also make that regexp global and match many
but that is outside the scope of this channel
Has the library been updated to allow for the "pending" param upon join to support the screening feature?
There is a pr for it currently, not merged yet
Okay, thanks!
I assume there is no ETA on it quite yet?
, it's probably gonna be included with the v13 release since there aren't any more planned v12 releases
Will v13 have breaking changes like v12 had?
Major versions generally do have breaking changes
Well dang..
Not nearly as many as v12, though
Why does <Guild>#equals() even exist
Along with <User>#equals()
Another like basically useless method is <MessageEmbed>#addFields() which I doubt anyone uses, which just adds more like clutter to the library
nah i think addfields should stay. people do use it and it makes code easier to read (ie you don’t have to have .addField 8 times in a row in your code)
it is for internal use, and perfectly reasonable as its description already says
oops i meant normalizefields @real jetty i copypasted the wrong thing
i meant to write <MessageEmbed>.normalizeFields(), idk why i wrote the wrong thing haha
sry
addFields imo is just... meh ```js
// addFields
embed.addFields(
{
name: "Global",
value: ${stats.globalWins} wins; ${stats.globalLosses} losses;,
inline: true,
},
{
name: "Per-country",
value: stats.countries.map((s) => ${s.name}: ${s.wins} wins; ${s.losses} losses;).join("\n"),
inline: true,
}
);
// addField
embed
.addField("Global", ${stats.globalWins} wins; ${stats.globalLosses} losses;, true)
.addField(
"Per-country",
stats.countries.map((s) => ${s.name}: ${s.wins} wins; ${s.losses} losses;).join("\n"),
true
);
Yeah for composition I prefer the former
Theyre statically used internally
ohhh kk gotchu , ty!!
If they are statically used internally, in es2021 are they going to be private methods?
The initial idea was to only have #addFields since it's much more verbose, doesn't bear the danger of providing arguments in the wrong order (which has often occurred in support) and takes a variable amount of arguments (field objects) which allows workflows like spreading or providing arrays of data objects.
However due to "feedback" from the community (read as: help channels being full of people calling the person applying the change (me) idiot, the library staff dumb and being very verbose about how much they hate the change) the method was re-introduced shortly after removal, after some proficient+ also expressed doubts in that approach. I might re-visit that thought in -next though, since a full on rewrite allows for structural changes like these to be perceived much less emotionally than in an already existing API.
Good point about the spreading, didn't think about that
Yet I still believe addField is better for stuff like my example
i don't but that's besides the point and nothing to be discussed here
Rather likely, yes, there isn't much reason as to why anyone would want to use that method in their own code.
Kinda hard to male them hard privates and then use them externally actually..
What? NormalizeFields is being used inside the MessageEmbed class, right?
If it's being used else where, then it can't be private
do we use that anywhere else 
no we don't
do we use TextBasedChannel as a typedef?
btw @vernal atlas the v8 refactor
https://github.com/NotSugden/yeetcord.js/blob/1bea1403bec653a76737dce99e74a136c62e2dc0/src/client/websocket/WebSocketShard.js#L597
is missing
intents: client.options.intents,
If it gets set in .ws then it's fine..if it isn't then it's a problem
it doesn't hence when you run the pr it throws 4013 invalid intents
resolved
who are the libary devs
~~https://github.com/orgs/discordjs/teams/developers~~ that doesn't load, nvm me
okay
uh, ok that doesn't load apparently 
can anybody explain to me how they made the VoiceState class bc i wanna make one for slashcmds myself
it did
#archive-offtopic for things not related to the development of discord.js
- the source code is public, you can look at the class implementation
makes sense
@vernal atlas another minor thing on the v8 refactor, in https://github.com/NotSugden/yeetcord.js/blob/refactor-v8/typings/index.d.ts#L2954
the typings give activity whereas it should actually be activities
so I've been looking into v8 PR by @vernal atlas and ran into an issue... message create is not emitted by the library for DM messages (https://github.com/discordjs/discord.js/blob/master/src/client/actions/MessageCreate.js#L10)
which makes sense since discord stopped sending channel create for DMs in v8
my question is, how should this be approached, should/will there be a new event just for direct messages that doesn't have channels?
oh interesting
or maybe fetch the channel and then emit message create?
I guess another option could be to just create a DMChannel with id (the only data discord provides) and go with it 
no auto fetching of incomplete structures
could also add recipients: [data.author] to the partial channel
could make use of Action#getChannel() (https://github.com/discordjs/discord.js/blob/master/src/client/actions/Action.js#L34-L49) here which does ^ but this would require the 'CHANNEL' partial to be included within the client options for it to end up calling Chanel.create(), ig an exception for the partials check could be bypassed for this case but thats a bit hacky
message.channelID and get channel()
Ref: Latest pin in this channel now deleted
overwritePermissions completely replaces all overwrites on the channel
createOverwrite and updateOverwrite are fundamentally very similar, however I think createOverwrite is supposed to completely replace a single overwrite if it exists, which updateOverwrite is supposed to merge with a single one that exists, or create if it doesnt
overwritePermissions is the most un-similar to the other two
At a low level createOverwrite and updateOverwrite are the same thing. However, because the overwrites are cached, they do both need to exist (and it makes it slightly clearer for users).
Further: the API endpoint those are calling updates based on the overwrite id, which will only ever be one overwrite at a time. Discord expects us to use the edit endpoint if we need to edit all overwrites (which is what overwritePermissions does)
Perhaps an updateOverwrites method would be better
Yeah, if you want to build a method which will analyse and diff the existing permissions rather than completely overwrite them, that should be updateOverwrites
Imo the play method should give a few more options to specify the type of the input and throw more errors if it doesn't know what to do with it/invalid input
80% of the questions in #archive-djs-v12-voice-deprecated are caused by d.js (or prism? Idk) swallowing errors and not throwing errors when something is wrong
Is there a reason why a lot of the structs exposed by the library aren't frozen? E.g Permissions.FLAGS?
I doubt it
Hey guys, I'm not sure if this is a good idea or not, so that's why im like putting it here instead of making a pr for it
Alright so basically, you guys know how the message object has a url property right? to keep it consistent wouldnt it be better to also make it so that the channel property also had a url property as well? imo it doesnt make much sense to have one url formed for you, and be forced to form the other one manually.
(I searched the docs for a channel.url property but couldn't find one, sorry if i missed it)
(Same thing for guilds as well)
eh
with channels you'd usually use a mention
which mirrors the client
the client only provides message urls and you can use mentions for channels
I don't actually see why you would want a channel url, it's pretty much only useful for exploiting client quirks like the old video chat stuff lol
idk abt any client quirks, the only reason this came to mind was cos someone was asking for it in support for an embed, and tbh it was more of a like consistency thing, but ig ur right and it would be kinda useless
ty!!
yw
would probably be a better idea to just generate an invite link for that channel, so users who aren't already in the server can still gain access to it
even if, that's definitely not something that library would do on it's own
wait r you talking abt the forming a url? Or making an invite link
Invite
ohh okey gotchu
I noticed during some debugging today that any method in a manager that deals with a Collection or Array of items will throw an error if even just one of those items is invalid.
This is fine, however the error it gives back suggests that the whole passed Collectoin or Array is invalid, not just a single item, which makes it difficult to debug.
I could see two solutions to this:
- Reject the Promise (currently behavior is throw, but I believe this is changing) with a newly defined TypeError that indicates that one or more of the internal items is invalid
- Silently throw out invalid objects / snowflakes and continue execution as long as there is at least 1 valid item left (obviously less desireable)
For reference, I found out about this by removing roles using an array of snowflakes. It threw a type error because one of the snowflakes was associated with a newly deleted role, but the error message made me think my database structure was messed up (I have handled this error before it gets to the method now)
Any thoughts?
@vernal atlas what if you made all BitFields use BigInts in v13 for consistency?
should not really matter (except for memory usage increase) if you use them with the flags, and you could convert numbers to bigints in the methods
well the only thing with that is its just useless conversion between bigint and number all the time
we can always break it altogether and not accept numbers
Honestly my only actual problem with keeping some as numbers is this line
const defaultBit = this.name === 'Permissions' ? 0n : 0;
thats the best way i found of solving it
maybe an additional param to resolve?
it seems silly to convert between bigints and numbers when you don't have to
it is
so then why suggest changing it all to bigints?
you can do that without converting
what
just bigint or it fucks
the api sends numbers for things like userflags
could just check loose equality
since 0 == 0n
equality of what
oh wait
nvm
for a start, why is this being done on the base Bitfield class
wasn't there gonna be a separate BigIntBitField? were they merged into one or can we just not tell the difference in this situation
given this.constructor.resolve is being used all across the board
the Permisisons class could just... overwrite static resolve
but then it would just be entirely duplicated code except for replacing 0 with 0n
default resolve can default to 0, extended resolve can behave like:
if (typeof bit === 'undefined') return 0n;
return super.resolve(bit);```
and it'd probs not be a huge deal
https://discord.js.org/#/docs/main/stable/class/Client?scrollTo=generateInvite should be updated to support the slash commands scope
Or maybe just add an option to give specifics scopes https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes
I much prefer the option to provide additional scopes
rather than forcing all invites to request application.commands
I would prefer it to
[...] forcing all invites to request application.commands
yeah, that's not gonna happen. array of scopes is probably what i'd go for
reminder though that interactions are still only in public beta
although we could definitely add that array of copes now and add application.commands once its finalized as I imagine there are already some use cases where more than the bot scope is necessary
sure, v13
I'l go ahead andl work on a PR for that
The slash commands PR has been merged, even if the slash commands itselves are in beta it is not a reason to not integrate it
Does Discord.js not support import {} from '' syntax? And if so why? If so what benefit is require() allowing?
That's more a node thing not supporting it in js yet, ts does support it though, and d.js does support ts
oh ok so what is the default export i assume just "Discord"
ah wait nvm sorry am a bit tired 😅
node 14 supports it
but you'll have to use .mjs or put "type": "module" in package.json
(and its unfinished so wont work for everything)
Well fair yeah, but as you said, it's still not 100% working, so no need to be pushing it until it is (just like interactions
)
Is there any plans for a Deno Package 👀
lol
I'd go out on a limb and say no, considering Discord.js is meant for Node.js. However, https://github.com/discordjs/discord-api-types does have support for deno
Supporting Deno is a headache with JavaScript, maybe once we go to TypeScript (discord.js-next), we'll have an easier way to support it. Regardless of that, we use a lot of things Node.js has that Deno doesn't.
deno does have a node compat layer tho
👋
User.presence.clientStatus returns an object, and this has got a major flaw:
For example, if someone logs in on mobile and logs in on mobile on another device, clientStatus would be mobile: 'status'
There is only one mobile object, meaning, the 2nd one wouldn't be displayed
This'd therefore be incorrect, would a PR changing this to something like an array of objects, with device as a string and status as a string be an idea people like?
Ping me if you have a question.
discord doesn't expose if there's more than one mobile device logged in
so that's impossible
Really?
Must've read it wrong, sorry
oh there it is, i just wasted 3 minutes trying to find it on User or Guild
also i have to ask.. like what?
It'd be nice if there was an option to broadcastEval on all available shards when not all of them have finished spawning instead of just erroring, should I PR one?
I'd personally be against adding something like that, given you can broadcastEval to a specific shard. I think it'd be better to leave that to each user to write their own util to broadcastEval to all shards individually and handle the error. Having a util in the library that does that might lead to folks missing issues, like a shard not starting etc.
The error is still thrown even if it's to a specific shard
Yes, but you can then catch that error and handle it yourself
I meant even if the shard has spawned already
there's no way to b-eval on any shard until all of them have spawned
🤔
That feels like an oversight on my part if that's the case
the error is thrown on the third line here - your added code is after that
Oh i forgot sharding in progress was a thing
maybe we just drop that err, cause each shard will throw a no process error iirc
if you dropped that line - from my understanding it would then just run for each available shard
and ignore the ones that are yet to spawn
(which would be the option I was suggesting)
Oh, this is when everything first starts
Yes
Personally, I'd be in favour of pulling out the SHARDING_IN_PROGRESS error, but then iterating over all expected shards and throwing an error further down if a shard hasn't yet spawned
I'm very against the idea of silently just ignoring shards that haven't spawned, but agree on ensuring its possible to exec on a specific shard before everything has spawned
I could work with that
Ig the for loop at the bottom would iterate over this.shardList instead, trying to find the shard in this.shards, and throwing something like SHARDING_SHARD_NOT_SPAWNED if its not there?
I'd just move the 3rd line under your addition for specific shards
it would be a lot simpler
Actually tbh yeah that achieves the same outcome
So should I PR that or will you?
Why is Guild.owner nullable but Guild.ownerID isn't?
because the owner member may or may not be cached
I got that part, but if it's not cached, how can ownerID be guaranteed?
because that’s provided in the guild data from discord
Hmmm ok. Thanks
Guild.owner is a getter on guild.member.cache with the guild.ownerID
Go for it 🙂
Cool, will do
@vernal atlas re https://github.com/discordjs/discord.js/issues/5227#issuecomment-762727900
Yeah I can def see this being an inconsistently reproduced issue depending on bot size and other factors.
If you check MessageManager#delete all it does is make the HTTP call - at which point d.js waits for the gateway MESSAGE_DELETE packet to actually mark the message as deleted
yeah
Yeah, it does depend on size, I can replicate with all code samples myself
It's an error due to eventual consistency
Cheers for bringing it up in here!
I don't particularly know how to even go about "fixing" this.
Most things in the library work this way, since Discord flat out doesn't really give this data properly in the http response
Yeah, in my case I'm thinking I'll just have to queue up my own collected events and process them FIFO
You could theoretically set it to true if Discord replies with a code 2xx (promise resolves)
but then that creates inconsistency
and lots of head scratching in other areas of the library
Yeah, we'd have to rely on the response code being 204 (in this case)
But even if I queue up what I'm doing, there's still race conditions around it
:p for now you could just do something like
const deleted = await message.delete().then(() => true).catch(() => false);```
the catch part varying on your scenario
which would rely purely on the HTTP request
The issue is, the message is deleted in one collect event, then the error is thrown in the next collect event - if I react between the fist event firing and the delete finishing.
ah, message collectors - that's a headache
Reaction collector
But yeah.
mhm
i'm not even sure if this can be considered a bug to begin with - neither do i understand in which use case this would be an issue
afaik the user client works the same way, messages are considered deleted and evicted from view and cache once the respective event arrives
so, wait, are you deleting the message yourself or are you concerned about someone deleting it?
My case is:
A message embed with paginated reactions. One reaction is assigned to call await message.delete() on the message the reactions are being collected on.
If you react with one of the other reactions prior to the delete finishing, the collect event fires again.
I have:
await reaction.users.remove(user.id at the top of my collect event, and this hits an error as it tries to get the message, which is deleted half way through the call
Yeah, I would agree with that, the message is not instantly deleted with the response, we could speculate on the order that discord processes things, but that wouldn't get us anywhere
ah
even if i check message.deleted first
it doesn't catch it
in that case you could just end the collector along with the mesasge.delete() call, though
That's true.
so that next reaction never comes through
Good point
But then if the delete fails, the collector is lost pre-emptively, state wise it can still end up inconsistent
and if the end user deletes the message... well... I guess there is the off-chance for the reaction to come in before the MESSAGE_DELETE, but that's so incredibly unlikely I'd just dismiss that edge case
but that is definitely a preferred option
well, it's your bot's message
the delete would only fail due to a sudden permission change or just Discord failing the request due to a 5xx or something similar
either case gets a shrug from me ¯_(ツ)_/¯
either case gets thrown into a rejected promise too IIRC
On a completely separate note, is integrating HTTP fetches for getters of user / member etc not in the cache planned for v13 or was that something that is happening later?
i don't yet see the necessity to introduce library side handling for this (message/other deletion)
pardon? you mean auto-fetching uncached partial data? has been discussed but been decided against for what it's worth
Ah, i must have missed the resolution to that conversation then
for larger use cases auto fetching uncached data could result in massive amounts of api fetches behind the scenes, with intents now being in the picture the whole ordeal becomes arguably worse (seeing that you might need to go with different approaches based on the data you receive)
abstracting that away into auto-fetches might even result in the developer never realising how spammy their bot even is. fetching data should be a conscious decision
yeah, I definitely see why it wouldn't be desirable, especially considering intents, just remembered seeing something about it and noticed there wasn't a PR
Again, going to a slightly different subject (but indirectly related) when passing a snowflake to something like Channel#createOverwrite(), the user has to be cached, even theough the API only needs the snowflake of the role or user.
This is actually due to attempting to type the data.
This is only one example, but I assume there are others that fall under the same category.
Since v13 will include improved type safety for Snowflakes, would it be feasible to pass Snowflakes directly if no cached object is available?
i was blissfully unaware that that's the case - with intents happening that's rather bad 
but i do for this one understand where it's coming from, since the type seems to be required, but can't really be determined based on the snowflake passed, might need to require that to be passed explicitly
@ruby terrace should prob. create an issue so that's on the radar (if you can find other places where similar things are happening do include those)
I’d be happy to (even to make a PR once the decision has been made) I’m just headed off to bed though, so will do in the morning
any idea why djs destroys sessions w 4000 instead of 1000 or 1012 https://github.com/discordjs/discord.js/blob/2583ad5da7db5ab92dfa357909f9c713db0a2981/src/client/websocket/WebSocketShard.js#L417
because 1000 kills the session on discords end
1000 and some other close codes
^
1000 means "all good, im out"
discord wont let you reconnect off of it
i... found that out the hard way.
it closes with 4000 so its able to resume its session because the session doesnt close immediately
I know v13 should be Soon™️, but do we have any documentation of the changelog or an update guide in the works? (I'd like my framework to be ready and don't see an in-dev branch on the doc site.)
Wonderful - thank you!
is there a reason it’s User.send instead of User.dmChannel.send?
or is it just for convenience?
User#send exists only because User implements TextBasedChannel which has the send method. However, in the code for TextBasedChannel#send you can see that if the object you're calling send on is a user or a member, it will just wrap around createDM and send to the returned dmChannel
ah I see
so basically dmChannel.send wouldn’t work if createDM hasn’t been called, and .send does that for you
so dmChannel would be undefined
Not necessarily? createDM will return the DMChannel if it's in the cache, otherwise it will fetch it
null, but pretty much, yes
oh i should probably move my discussion here
i didnt see this chat earlier
why Guild#addMember instead of GuildMemberManager#add ?
BaseManager#add already has specific functionality which that would clash with
But your point is still valid, it could be on the manager with a non-clashing name
yeah i opened up a fork and looked around to try and do a PR for it and I found that
so my question now is why is there a BaseManager class that 2-3 managers decide not to implement
Those are fake managers lol
uh
is that concept explained somewhere
Probably not no
what's a fake manager then
and why the need for it
just looks very off to me at a first glance to have one manager reimplement part of the base without extending it or something like that
by fake managers are you talking about things like ActionManager?
no
nvm I got a little mixed up
But Im not sure why this is a concern for you?
This manager does have custom a custom add method
well its a concern to me because i was going to go in and move the code on over from addMember to members.add
and then i see that, so I'm like, "okay lets look at the base manager to see what this does"
those managers are pseudo-managers, meaning that they don't have their own cache but instead get/filter it from another cache
Right, nvm, its because these have a fake cache
Yeah
so i look at it and i see it doing the cache, and I say "oh cool, but wait, you can do member.roles.add, so maybe I'll look at that and see how that's implemented"
so i go there
and it's completely different
fake managers are needed for the getters correct? like GuildMember#roles
Well that is the manager
roles.cache is the getter, yes
ah okay
yeah ok I see how this works now
So they dont extend BaseManager because you cant override a real property with a getter
so how are we going to fix the addMember issue then
best way would probably be a non-clashing name right?
that seems fine but I don't agree with naming it anything other than "add" though, seeing as the discord API call is literally named "Add Guild Member"
you could use GuildMemberManager#join maybe?
that doesn't make semantic sense either
I was thinking of like
User#join
or joinGuild
joinGuild probably works better
if we have methods available such as member.ban() and member.kick(), I dont see why user.joinGuild() is inconsistent
having it be a method on User requires the user to be currently cached, no?
The current method accepts a UserResolvable which includes ID only as an option
^
well to stay in line with consistency as well as fulfilling the requirement of it being a userresolvable, the only option is GuildMemberManager.add
for my use case at least, the user is cached beforehand
...which still isn't a valid option though
in most cases it won't be though
yeah i agree
you can add both, seeing as you have member.ban() and guildmembermanager.ban(userresolvable)
why is it not a valid option @frank turret
like, semantics and design wise
pretttyyy sure member.ban is just a wrapper over guildmembermanager.ban
yeah that's my point
i mean sure, a convenience method is fine
at the end of the day i just see a massive inconsistency here
everything was migrated to use a manager system in v12 then out of nowhere we get a .addMember
lol
which brings us back to the option of guildmembermanager#join lol
yeah but i dont agree with join
the api call isn't called join
Here's two possible thoughts:
- add a parameter to the add method in that indicates the user is not already in the guild (I strongly dislike this)
- add a new function named something descriptive, perhaps like forceAdd
forceadd also semantically doesn't make sense
it might be inconsistent, but we have no choice, we can't override a basemanager method that would literally break it's functionality
the only way I see design wise to be consistent (if we exclude the issue with implementation for now), is if we add guildmembermanager.add and user.joinGuild to wrap around it
pls dont mind my lazy typing for those methods
mmmmm then what do you propose we do about the existing basemanager method then?
cause if we override it, there's tons of places in the lib that are gonna be broken
@ruby terrace my thought is that having add and forceAdd both exist is a bad idea because that implies that:
- add is an action that may fail
- forceAdd does the same thing as add except in some way forces it to not fail
@frank turret the issue here is with the fundamentals of the manager system at this point
i also disagree with .join because the API method is named add
and, read this: guild.members.join(user)
oh, addUser might work, since you are adding a user to the guild, not necessarily a member
the guild's members aren't joining the user
🤔
maybe rename manager.add to manager._add?
@ruby terrace no that's also bad, because again, the API method is named "Add Guild Member"
dunno if its considered private
you are not adding a user, you are adding a member, therefore you don't use addUser
users aren't supposed to exist within the context of guilds, only members
you cannot add a member though, since that member doesn't exist yet, you are adding a user, which creates that member
well in dAPI, it's referred to as adding a member https://discord.com/developers/docs/resources/guild#add-guild-member
well at that point that's a gripe with the discord api docs
doesn't guild.addMember require oauth
it does
i'd assume d.js to follow the docs , and not opinionate them
it does
yes, it does
shouldn't matter though
so why are we trying to force it so hard into base d.js
because oauth is apart of base d.js? The method already exists on guild so you can't argue that it isn't already in base djs
you want to have proper api coverage right?
like, on the homepage of djs website?
almost 100% coverage?
the only thing this convo is talking about is moving said method to the more consistent placing
i mean the coverage is there but the implementation is flawed
what flaw
where
read above
i did
"inconsistent naming"
there is a lot of words above, which don't mean much
to my knowledge, Guild.addMember is the only use case of similar methods not being in <manager>.add
the ONLY case
and it's an inconsistency
only because of the clashing base method
yup
so the problem at the core here is the fact that internal manager method naming clashes with potential API naming
that was something that shouldn't have happened to start with
so then i like Jan's suggestion of moving basemanager#add to basemanager#_add
since it is only used internally either way
I think that's a step in the right direction, but I feel it might still be confusing and there might be a better solution
maybe something where internal manager code is abstracted from api calls
well so far you haven't really provided any other alternative, you've only said to replace the add method, no solution as to where we are gonna move the existing method
the issue doesn't disappear if I don't have an alternative
and I was typing something
how has API coverage even come up as argument in this discussion... adding members through oauth2 is covered.
because someone above asked "why are we trying so hard to force X discord API method into discord.js"
that was not what i said
could you rephrase then because I may have misinterpreted you then, mb
so the real argument is Guild#addMember should be Guild#members#add?
okay. yeah, sure
yeah
that's what I think
so can that be the actual point in the discussion please?
not... whatever else what discussed up there
well that's what i brought up initially but it got trailed off
well that's what i'm trying to discuss
@frank turret if you want my idea for an actual implementation that prevents the name clashing, i suggest an abstraction between core manager code (managing caches, etc.) and 1:1 wrappers around API methods
for example, one could use the guild.members to not return the entire basemanager, but rather a scoped proxy or something on the basemanager that maps calls to manager._api.X or something like that for example
that way you could have manager.add, manager.cache, etc. all that stuff, and have all 1:1 discord API mappings outside of that layer
that way there would be no possibilities of a name clash
the point of managers is to separate cache and api 
well, then we have an issue, because that's exactly what DOESN'T happen when an api method named .add can't be implemented on a manager because it's cache needs it to have an .add method
that's exactly what we are discussing
in this case, they seem to be implemented incorrectly
whats blocking you from just doing guild.members.add
where is that api method named add again
why are you bringing a 1:1 mapping djs <-> discord API up? that's not a design goal
basemanager#add, that's what
@oak quail https://www.threebow.com/i/681dc8942dbf.png
we got this
and basemanager.add yeah
oh is there an undocumented basemanager#add
yeah its undocumented
it doesnt show in docs even with private on
yeah i just tried it, it's weird
i think these comments need to be fixed
i dont know how this jsdoc and that method are related
not at all
tbh i'm confused as to why add is a thing, isn't that blurring the line between separation of cache and manager?
so there isn't anything to fix either, if anything there is docs to add - to add
no
the issue is that .add does something other than the add api call

@frank turret yes, that is my entire point

that's what i've been trying to say
Then i guess i've finally understood you, mb
though your solution is going a lot farther than what i'd think the solution would be, which would be to just remove .add
you're thinking of the next managers revolution type stuff
well thats what you get when you find a fundamental violation of separation of concerns
my point: if the goal is to have an abstraction layer between an internal cache mechanism and API consumption, the very fact that there is a possibility for a name clash to occur on the same class between the two proves that the implementation is fundamentally flawed
looks like BaseManager.add is a left-over from DataStore
manager.add was added as "create a new instance of this.holds, and add to this.cache if it doesnt exist yet"
@frank turret the solution may also very well be to just remove add, if it is a leftover from something. however, i dont know what impact that would have as I'm not too familiar with the inner workings of the lib, so that would need to be checked by like everyone
the very fact that there is a possibility for a name clash to occur on the same class between the two proves that the implementation is fundamentally flawed
not exactly? this would mean that a manager has to have exactly 0 properties on it, as virtually anything could clash
the manager doesn't have to have exactly 0 properties, the object given to the user when requesting the manager should
abstract the api away from the caching
tbh that just feels like a layer of abstraction too far for the end user to have to learn
so how would you manage cache of a manager again
I explained above
no
weeew I missed a lot
This channel does not need this much argument, god damn
you have all caching mechanism-related methods on the manager, using the existing add/set/remove/whatever it needs. then, in the API that the end user uses, for example guild.members, you return a wrapper around the manager that exposes only dAPI methods instead of the manager itself, using a proxy or something
It's just discussion, overly drawn out discussion at that
that wrapper then would control the interaction between the two
so from the user's side of things, they would ideally only get access to API methods
Yeah but this is now so far removed from what the discussion was supposed to be about
I dont see how that is, I was answering the question of how I'd implement a solution to the problem personally
the discussion's still about the core problem
and how do you access actual members via this propertyless manager proxy?
there isnt much on BaseManager
add is the only thing i see thats problematic
yeah
that's the whole issue
but seeing as it's used internally and causes a name clash with a real api method, here we are
We can call our stuff whatever we like though
yeah im not denying that, i just figure in the name of consistency that it wouldnt make sense to have Guild.addMember
just renaming it to _add should resolve the problem
or if we dont want to break too much
ya that too
making it _add in guildmembermanager specifically
guildmembermanager already has a ```js
add(data, cache = true) {
return super.add(data, cache, { id: data.user.id, extras: [this.guild] });
}
then comes in the question about consistency
How would that work?
but this argument is about a fundamental flaw in the method existing in the first place - which it really isn't. the manager manages the data saved in the cache.
meaning half of this way too long thread is void.
two options IMO, you either feign the API's "get user" method to return a cached user if they already exist, or just let them have the cache method
so we could just make that _add and overwrite add to be addMember and be done with it
but cache where
on the manager
but how do you access that
the manager will still manage the cache
for example guild.members, you return a wrapper around the manager that exposes only dAPI methods instead of the manager itself, using a proxy or something
yes
most fetch methods already try to get from cache first iirc
why?
enlighten me
how do you fit a manager.cache into manager that has no .cache
does anyone have any objections to this
I can word that better, what I meant wasn't directly allowing certain methods of the manager to be exposed and others not
I'm not a fan of having both add and _add
nor am I
here, I'll write out my idea + some code basics
addToCache?
since it's going to be a lot easier for me to explain it that way
Please no
Sorry wrong reply
addToCache bad because you have .cache prop
only objection i have is on the basis of consistency with the other managers, why not do the same change for all the managers in the event dAPI ever makes another endpoint that clashes. Why not make all manager specific methods have that _ notation
i dont have any issues with that
(other than its more changes)
@frank turret the future proof-ness of "in case they ever make a new one that clashes" was also a core factor in my solution
This is supposed to be a channel for raising suggestions / issues to the actual maintainers and developers of the library. Arguing over the naming of a property is exhausting
well it's not just about the naming anymore at this point
What you're now proposing belongs in the -next lib imo
the naming is a problem due to another underlying issue and that's what i'm talking about
I'll take my leave from the discussion, as my last message is probably my final stance that i've got on it
not too familiar with -next personally
is that where you do like
v20 or something
I do agree that it would definitely be a change big enough to the point of it probably belonging in a repo like that
Its a typescript rewrite
its a planned ts rewrite, pretty empty rn
ah
neat
yes? it adds it to the .cache
So you'd be able to properly flag properties as private
so .cache.add()
No
but that clashes, because .cache is collection
We're not going to be changing Collections
Rule that right out
I didn't suggest that, I'm bringing up the issue of what @oak quail is saying
I agree with you lol
but this argument is about a fundamental flaw in the method existing in the first place - which it really isn't. the manager manages the data saved in the cache.
meaning half of this way too long thread is void
again.
But its not what he said 
He said .addToCache
ok I want to reply to like 4 different people but it's so difficult to keep track of this
Yeah, GuildMemberManager#add is the edge case here, not BaseManager#add
@unique axle i was going to type a reply to that when you sent it but I got caught off guard by everything else
me calling it a fundamental flaw was based on my assumption that there was a goal of separating caching from apis
then do me a favour, stop writing, read
and then decide if a response is still needed.
this entire chat at this point reads more like a rant than like a legitimate suggestion, which i am very much not a fan of.
Is there a reason that method exists in the first place? I mean, it’s the only OAuth method that exists in the library afaik
i have had "give me like 5 mins, I'll write something up" pasted in my clipboard for the past three minutes
requires a bot token and the bot's permissions matter, so its basically a bot endpoint
but i have to keep overwriting myself because everyone's bringing up like 5 different things
It requires an oauth token from the user to use, but its a bot API method
yeah tbh I agree we should keep that api method in the lib
it is a bot method
that has been discussed before, it stays, it's part of the bot API, not the oauth2 api - despite requiring an oauth2 flow to receive the required token
@unique axle so the core thing that I based my argument on originally was me hearing somewhere that managers existed as a way to abstract api methods from caching
if that's the case, then I believe what I say to be valid
but if it isn't then i'm wrong
and I remember reading something like that in this chat before I made that point, and that was my reasoning
I can try and find it rq
yeah this one
I know less about the intended design of the stuff than you guys do so if you say that this isn't the point then that's fine, but that was the presumption that I made my points with
again, cache is a data structure, nothing more
the manager acts as... manager, to manage said cache, add and evict data - however complicated that might be
which also makes Basemanager#add completely valid to be on the manager
it allows the adding of data to the underlying cache without having a ton of code duplication when the api is called from various places
yeah, I understand that, I never proposed we get rid of caching from the manager
but my question now is that if the manager acts to manage the cache, then why is it also responsible for wrapping API calls
you argue that #add should not be on the manager - for whatever reason
Because thats what API calls do
Manage cache
fetch? into cache
kick? remove from cache too
edit? update cache
I dont think you guys are fully understanding the solution that I was proposing to the issue
There's a rather big nuance here
a rather big nuance is as well that you are proposing a solution to a problem that doesn't exist
We're allowed to understand but not agree
I didnt say that method shouldn't be on the manager itself entirely, I said it shouldnt be on whatever the end user gets to work with
the only thing that actually should be discussed is moving Guild#addMember to GuildMemberManager#add and renaming the Basemanager#add which conflicts
You're proposing yet another level of abstraction between cache/manager/wrapper of that and I fundamentally disagree that its necessary
@unique axle well if you find a way to do that that would be good, but assume later down the line for example discord somehow adds an API method to whatever you rename BaseManager#add to (assuming you dont call it _add or something, which tbh I disagree with because then you'll have .add and ._add on the same class and that'll get a bit weird)
considering there's e.g. Base#_clone and GuildChannel#clone too, i dont think _add would be a problem
since it's calmed down a bit here, an example of my solution would be to still have the manager handle all the cache-related stuff retaining the problematic BaseManager#add, etc. - the difference is that the implementations of all the API methods would be on <IndividualManager>#api or something, and when somebody requests for example guild.members it returns a proxy who's entire job is to facilitate cooperation between the api and the manager's cache itself
But the proxy would only actually return methods defined in the api child, not any of the internal manager methods involving cache manipulation
and maybe a .cache object as well that acts the same way as it does now
That way it would be effectively impossible for there to be any name clash
keep in mind that idea is overkill for this little thing, and would definitely be better suited in a rewrite. if renaming and moving around a method or two is all it takes to fix the .addMember inconsistency then I'm all for it
but just something to consider for the future
if it's consistent then sure, but then my question becomes whether or not those two methods existing in the first place is the best way to do that task
I disagree that's necessary. The manager is already facilitating the cooperation between the API methods and the cache itself. I don't see the perceived issue with the user being presented with methods that operate on the cache also.
The only demonstrable example of this is add which can be addressed by renaming it to _add
my idea comes more from my POV that code that may need to be fixed in this exact same way if another example of this happens at some point is not maintainable
I dont think a major refactor is the answer to that
i understand that it's not the most efficient way to deal with that in respect to time constraints and whatnot, and if you can get away with renaming a method because you got a name clash and it'll save time then by all means do it, but there's no guarantee that this kind of thing won't pop up again even if rarely
in my eyes I don't consider patching this one instance out as a true fix to the underlying issue, that's all
that's also why I said it's definitely much better suited to a rewrite if you're already doing that
I really disagree with the pattern of adding underscores to a conflicting method to fix the conflict, because that becomes a huge pain in the ass really quickly from my experience
but it's your library - as you said, you don't have to agree with anything, I'm just bringing my input to the table
The underscore is normally used to denote that a property is only intended for internal use, since Javascript has no private typings for class methods (or didnt until a very recent TC proposal)
I'd say its more that a naming clash has flagged that this method should have been underscored, because BaseManager#add is intended for internal use
well what classifies internal use vs non internal use in this case
like, exact same thing as private keyword in other langs?
Roughly
i'm also not too sure how you rely on a system like that
javascript doesn't have actual classes
Exactly
it's not real OO
Exactly
so i dont know why you're trying to feign private accessors with _'s in the first place
Because it communicates to users that its not intended for use
This is no longer library discussion, really more about general practices. This isnt a uniquely djs thing
seeing as you use these practices in the library i'd say it's discussion related to the library though
Tbh if that's the only inconsistency then there's no issue besides fixing it
Respectfully I dont really care what you say it is or isnt and I, as staff, am trying to move tangents out of this channel and stop this circular discussion from covering the same points all the time
.referencedMessage
READ-ONLY
The Message this crosspost/reply/pin-add references, if cached
seems weird to say "if cached" when its provided by the api?
it's only provided for replies, not crossposts etc
is it weird? Cause looking at dAPI docs on the you only get the message id, channel id, and guild id, so wouldn't we not be able to provide that prop if it isn't cached?
api provides referenced_message on replies (usually) and pins (in some cases)
not always though
can't believe i overlooked that
Does it when you fetch
Its also possible to have a reference deleted
tl;dr there are valid cases where it wont exist in cache
Also a really obvious callout - messages that are not replies
I have no idea if message cache sweeping would clear them out at the same time or not
@pearl basin i pushed a fix to send the message event - but for the moment it requires having the channels partial, is the best route just removing the channels partial and then dm channels can just always be partial?
yeah
tbh, would probably be a good idea to just allow anything to be partial and to stop dropping events by default
what is the use of the channels partial even? I mean... When is the channel not in cache except for DMs?
you just answered your own question - reactions on uncached messages in DMs
so only DMs 
idk I'd remove the partial and just put "events that happen in DMs might have an incomplete channel object" in the changelog
TYPING_START on an uncached DM channel is also probably a partial (?)
I think long term that may be a good idea. Furthermore, slash commands might affect decisions around this, if the bot isn't it the guild, can't fetch the channel, so almost guaranteed partial unless they decide to send the channel object with interactions
how would removing functionality be a good idea?
if you don't need the partial, don't use it - i don't see any reason for it to be removed, it covers an edge case that exists in various use cases
Having to enable a partial to be able to receive a DM 
gUys heLp mY bOt nO reCeIve dMs
{200 lines of shit code here}
Oh, I don't mean removing partial functionality, I mean having partials be expected (since that's how the API handles it) especially with interactions where there is no bot user
it's a small change but it's still gonna cause a lot of confusion for those who... Uh... want to make a bot but don't want to learn programming
i have no idea what you are trying to get at...
you don't have to enable partials to receive dms, you have to enable partials to receive events which depend on dm channels
which are DMs
lol
(since v8)
Still no idea what you want or are saying
Oh I'm just agreeing with this
Sum up: DM channels will always be partial unless manually fetched with v8 gateway, meaning users won't get DM messages unless they have channel partials enabled
@vernal atlas about your comments at https://github.com/discordjs/discord.js/pull/5130#pullrequestreview-555106805, do you suggest they should all be required?
@wild flax having strings for bitfields still usable is defeating the entire purpose of the pr
well yeah thats what the type is for isnt it? (referring to ping above, forgot to reply mmmmm)
like:
GuildAuditLogs.Actions.BAN_ADD should be a number not number | undefined
nah, I think the PR is still great for what it is, not promoting strings anymore.
I think we can evaluate completely eliminating strings with the typescript rewrite
but this is def a step in the right direction
so do I add a deprecation warning?
Nah
Just what I said will be totally fine
will do
We can always add it later when we have a good path for the rewrite
@vernal atlas whats the point of this commit https://github.com/discordjs/discord.js/pull/4879/commits/8532201e5c204429f6a3e5263c3ac9bed35b8525
new permissions and all are just pure strings now because of big ints
why should we accept a number?
it was to accept compatibility when extending the class
so that for instance UserFlags still uses numbers but Permissions uses bigints
ah
all good then
would you say discordjs/collection#31 warrants a version bump/new release?
yeah
a major one even
because of the node 14 bump
@ruby terrace I converted your issue to a discussion btw, just in case you wonder why its closed https://github.com/discordjs/discord.js/discussions/5242
Ah, thank you, forgot those were a thing
any thoughts on making Collection#array() and Collection#keyArray() getters?
any thoughts on removing them altogether? No..? just me? ok
they're used internally for some other methods 
and they're more less a cached [...coll.values/keys()]
Personally against. In my mind having it be a getter gives some impression that it can be used to mutate the collection, whereas as a method mentally there is a clearer distinction that its generating a copy.
at what size does that caching mechanism actually become noticeable?
I mean you'll probably notice it at any size if you really monitor each byte of ram used, however, I'd expect a bunch of ram used if you, say, call members.array() on a 100k members guild (assuming you have all members cached)
Yeah... there are cases where the caches bring more bad than good, members.array() is a good example
So what about a potential bool to indicate whether a cache is warranted or not
what's a use case for caching this anyways?
But it's mostly useless, because:
- When the collection is small, the values are barely added/removed, but creating arrays on the fly are so fast it's negligible.
- When the collection is big, the values are added/removed very often, which voids the array almost instantly, forcing re-arrays anyways.
Having this cache layer also adds overhead in the set/delete calls, even for those who don't use the array caching
so is it better to remove just the cache or the whole methods 
Both
I believe .array() was originally done because we didn't have [...iterator] back in 2017
we need a major for this anyways, so might as well do it now
we can keep the method as a shortcut
but drop the caching aspect of it
Hi, i have a question about ratelimit/api on this function .remove(arrayofroleids) when using an array of role ID's.
Does this count as 1 request? (see gif)
if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { ... return this.set(newRoles, reason);, single API request
ahh like that thank you so much! ❤️
If you pass a single, the lib sends a delete request to remove the role from the user. If you pass multiple to remove, the lib sends a single request to set the users roles to what remains
oh wow, thats interesting. thanks for clarifying!
but does it still on the api side use one rate limit request?
yes
but the two endpoints have different buckets
well theyre the same but separate
so if youre just adding/removing one role at a time you can technically use both endpoints to do 2x the amount without getting ratelimited
im surprised how detailed of an answer you both gave me fjdiosaj thanks again! it was definitely helpful
have a nice day : D
oh just wondering, is it also possible to remove/add an array of roles to an array of members with only one request?
nvm probably not
nop
no
haha thanks :p
questions regarding library usage go into the GET HELP HERE category as well
got it! sorry
collection exports are still kinda broken btw 
exports.Collection = Collection;
Collection.default = Collection;
module.exports = Collection;
exports.default = Collection;
should probably just remove the module.exports = part
module.exports = messes up the exports referencing module.exports
And this is after @warped crater already "fixed" it 
looking back - yeah, it was obvious that would've never fixed it
module.exports is being used here since export = (the proper syntax for this) would throw an error
since TS does not like that along with any other exports in the file
me and I think Vlad(?) also suggested removing module.exports =, but we were shut down by Crawl due to it being a breaking change.
they can be removed now
how do you wanna go about versioning?
per semver since we're on 0.y.z we can just bump y for breaking changes
things are getting deleted literally now
oh, lovely
I'll PR then
we cant remove the default export
so doing export class X wont work
except TS does some magic that you can do export class X and then still do export { Collection }
not sure if it allows that
it allows you to do both export class X and export default X
export class x = export { x }, we can export default it too I suppose
thats not what im saying
pure class X acts as an assignment
like const x = class X
uhuh..
but does export class X do the same
so you can have export class X {} and then later do export default X
let AttachmentArchive = class AttachmentArchive {
ticketID;
originalURL;
archiveURL;
};
// decorators here l o l
exports.AttachmentArchive = AttachmentArchive;```
short answer, yes
so TS itself, before compilation doesnt complain?
it doesn't
aight then, sure
ah, so we're doing that? sure.
wait so is v13 gonna be a ts-rewrite? or naw
no
d.js-next will be a ts rewrite. v13 is planned for the api v8 release, which is coming out sometime in the near future
ohhh kk gotchu
Is there a specific reason why some api-route crafting functions use foo[id] instead of foo(id)
For example:
https://github.com/discordjs/discord.js/blob/8a7abc9f06d44bf693e35a615bb6ba2c3eb1d6e7/src/managers/MessageManager.js#L84 is ```js
this.client.api.channels[this.channel.id].pins.get()`
<https://github.com/discordjs/discord.js/blob/8a7abc9f06d44bf693e35a615bb6ba2c3eb1d6e7/src/managers/MessageManager.js#L126> is ```js
this.client.api.channels(this.channel.id).messages(message).delete({ reason })
probably not
i think the convention is to use () for ids and [] for url parts
there really is no convention
i honestly believe that we should remove the possibility of () for those
keep calling the function to the request itself
I've just PR'd a change to enforce brackets
why?
@unique axle you commented on #5256 referencing #5256?
i've updated what you pointed out, though

i'm smart.
can you please wait for feedback though, before you apply reviews regarding a change you propose on other prs?
this is far from decided and suggesting that as required changes on the api v8 PR is not a good thing to do yet
you're correct, my bad
and as for why it is needed
consistency, mainly
Why Message#member does not return a partial member (if partial enabled) if the message is coming from a guild (and not a system message or any other necessary check I guess) ? https://github.com/discordjs/discord.js/blob/master/src/structures/Message.js#L278, same for https://github.com/discordjs/discord.js/blob/master/src/structures/Message.js#L413
because API sends member object with the message
true, https://discord.com/developers/docs/resources/channel#message-object lists member as "partial", but what API consideres partial is irrelevant to what discord.js partials are
See
** The member object exists in
MESSAGE_CREATEandMESSAGE_UPDATEevents from text-based guild channels. This allows bots to obtain real-time member data without requiring bots to store member state in memory.
under link above, and
The fielduserwon't be included in the member object attached toMESSAGE_CREATEandMESSAGE_UPDATEgateway events.
under https://discord.com/developers/docs/resources/guild#guild-member-object
I see, thank you!
is there a reason why PermissionOverwrites doesn't extend Base? assuming they do have IDs
Represents a data model that is identifiable by a Snowflake (i.e. Discord API data models).
PermissionOverwrite is not. The ID you refer to is the ID of the target of the overwrite (user or role)
this ID does not uniquely identify an overwrite (you also require information about the channel)
what about e.g. voicestates? same thing should apply there
going by the description of Base, yes
unless i'm misunderstanding the description and whoever wrote that does mean a snowflake to be used as key for a map containing the structure, which then would also make scoped unique valiable
i think you're right about the description but it's not really consistent there
there can even be some Bases without any id, like reactionemojis representing unicode emojis
indeed 
consistency is noticeable by lack thereof
so would the decision be to change the description of Base or go forward to make the class extend Base?
considering that's (almost) the same case with voicestates. or rather, the description seems quite misleading at this point unless your first guess was correct that it holds "structures mapped by IDs"
Just a little bit of curiosity, why is it that the client events don't pass some sort of indication of who did the said action, rather than just giving the old and new object? Is this subject to change, am I missing something? Or is currently the only way of getting the user that did an action just fetching from audit logs for it?
we can only provide information we get from the WS, discord does not give that information without requesting the audit logs
Ah, alright thanks
What if we removed Util methods from the default export?
I really can't find a case where I preferred to use them over importing Util
i think someone uses it
the Util.mergeDefault comes in handy
i'm not saying remove util
but you can currently call Discord.mergeDefault like Discord.Util.mergeDefault
why make -next a monorepo?
Developer convenience, theres no reason for it not to be right now I think was the general sentiment
I mean I'm down.. idk about others tho
What else would it be
separate repos?
but why
monorepos are so much easier to work in
its the common approach nowdays for large projects
apart from the fact that you can't install a single package from the branch like npm i discordjs/discord.js
so you can only work with the repo itself / the releases
so you have to update 4 different repos, then go to the main repo, change all the deps to latest and push another update?
essentially switching 4 repos for 1 change?
well not every repo would need to be updated for every change, I assume most changes wouldn't need that
We would, @oak quail
For example, most of the monorepo's packages will depend on @discordjs/core, however, there are dependencies between them, e.g. @discordjs/rest depends on @discordjs/core and @discordjs/collection, similarly, @discordjs/ws depends on all the previous (including rest)
are we going to rewrite collection too?
It's already rewritten? Unless I'm missing something
@mystic meadow what if you had to import a version for discord-api-types and just import 'discord-api-types' would not be possible?
yeah, i was wondering because i saw a collection directory in the -next repo
?
you currently can import any of:
import ... from 'discord-api-types';
import ... from 'discord-api-types/v6';
import ... from 'discord-api-types/v8';
i am sort of suggesting to remove the first option
so no api version confusion ever
To remove the default version export? while doable, you need to specify SOMETHING on the main/types properties of the package.json
you don't
I'm still against dropping it as there are still exported properties that aren't versioned (JSON errors for one)
then you could have disocrd-api-types/common or discord-api-types/errors or any other thing
just eliminate the default version
when the ts recode comes eventually, how will the typings look? will there be one typings file or several?
and I’m assuming they’re still being exported
the purpose of writing source code in typescript is that you wont have to create declaration files at all, the compiler does that for you
oh so everything is just gonna be defined on its respective class
How will they be exported?
export * from '...'
Yeah but how is that gonna work on like a Message structure
I assume that'll exist within the core
Structures that are meant to be extended will be exported possibly the same way as they are right now, CC @solemn oyster
Extending structures in -next is gonna be completely different to how it works right now
There is no way this will be comparable
do you have any plans you could share to me? 👀
I'd assume just a DI approach such with something like tsyringe
I wrote this like a month ago, mind you, Im sure I can come up with something better, but youll get the gist
import "reflect-metadata";
import { injectable, inject, container } from 'tsyringe';
@injectable()
class CustomChannels {
public test = 'test2';
}
container.register('CUSTOM_CHANNELS', CustomChannels);
@injectable()
class Channels {
public test = 'test';
}
@injectable()
class Client {
channels = container.resolve(this.customStructures.CHANNELS ? this.customStructures.CHANNELS : Channels);
public constructor(public customStructures: any) {}
}
const client = new Client({ CHANNELS: 'CUSTOM_CHANNELS' });
console.log(client);
but it goes into that direction
👍 from me
That would only work with TS tho
Nah, tsyringe also works with javascript
mmm, I remember reading something about that
but what are the approaches as an alternative to the decorators?
You could use babel (https://babeljs.io/docs/en/babel-plugin-proposal-decorators) or something unholy like that, but I'd assume there's a clean programmatic method to get the same effect, right
you can just register them to the container I guess
Not that I care about pure JS users
not... certain I share that sentiment given djs was always known as being very user friendly and easy to get into, compared to other libraries
then again, extensions are not easy to get into
as much as I also hate vanilla js
as long as its doable in raw JS, i'm down
