Check if embed, actionRow etc. has been modified
Hello
With the InteractionResponseModifyBuilder, we can define actionRow, embeds etc.
However, I would like to avoid to send the same content to the API (to reduce network interaction)
Need:
So if my message had 2 embeds and 2 actionRows, but only the actionRows are modified since the last rendering, the request must send only the update about actionRows and not Embeds.
So naively, I thought to verify with equals the old and new actionRows built, but that not works. For example
have you a better solution to do that?
58 Replies
Check each property manually
That's how I did it in the KordEx welcome extension
We should create the equals method in kord, that should be more simple for everyone no?
it would, of course
@LustigerLurch @SchlaubiBus An opinion about that? (sorry I don't know who maintains hardly the project)
If that's great for you, I will create a branch etc. to do that
Have you the link of the files that your created for that? That could be helpful
it was an actual bastard to write
https://github.com/Kord-Extensions/kord-extensions/blob/root/modules/functionality/func-welcome/src/main/kotlin/dev/kordex/modules/func/welcome/_Utils.kt#L52
disgusting code
lmao
Oh wow
Yes, we maintain Kord.
As for comparing builders with builders or builders with entities, this seems like a hard thing to do for a few reasons:
* It's not very clear to me how optionals vs. nullables should be compared (I have the feeling even Discord isn't really sure what means what for those). Is a
null
value and an Missing
value considered equal? Kord builders are written to only expose nullable types but can be backed by an optional and nullable value that changes from Missing
to null
on first assignment. How do we handle this?
* If we'd like our API to be consistent, implementing this would mean a lot of work to do for all builders (we'd have to implement equals
and hashCode
for a lot of classes).
* There might be some property of some entity that isn't relevant for the comparison in every case, think of something like edited_timestamp
for messages. How do we decide which to include?
If possible I suggest to have some custom logic for this on your side instead, here is an idea how to do it:
* Have a (data) class that represents the content of a message and use that data to "render" the actual message.
* Keep a reference to an instance of that class representing the last sent message. You might also persist it somewhere if needed or reconstruct it from a message.
* Use that to determine which parts need to be updated.
I imagine something like this:
- Yes I think missing and null are similar, so the compare will not be harder. For the equal and hashcode, we just need to consider missing as null and all builder will match
- That's true, but I think that could be a real benefits for developers. As you can see, I need this feature, in kordex too and I easily imagine that other devs need this for some components
I can initialize this for all components and for the next time, we just need to maintain them in case of new fields (that will not be hard)
- I imagine
edited_timestamp
is a field where the value is invented by Discord API and not the dev. In that case, we can create the basic equals for all fields and maybe a isSimilar
method that ignores these types of fields.
But in reality, the use of Equals and Hashcode will be used before sending a message, so only the fields defined by the dev will be present, in that case, if I have an object with toto
and titi
fields and defined values for both, I would like to compare all values not partially
Yes that could be works If I create my own EmbedBuilder and transform it in the final step to a Kord.EmbedBuilder but if everyone needs to do that, that could be annoying for a lot of developer and I think a library should be easy to use to realize a common feature
@LustigerLurch can I try to create a branch and will see what the result will be?the thing is, you still will have to write some code similar to
renderWelcomeMessage
, that won't changeYes but I think, I can handle it differently with equals and I would like to try it if possible
how would you do it?
For my app, for the moment I have different component (Embed, Button, Text, etc.) and each inject directly a new data in the dedicated builder
So yes basically I can duplicate the builder structure but that's annoying and personal. Create equals will be helpful for everyone
Honestly I don't understand the problem to do that, the equals and hashcode are common function present in all objects. So there is no specific difficulty to implement them
So yes for the moment, according to my app, I need to duplicate the code like that.
The only advantage I see to do that in my side, is I can customize the builder to add function, but that's possible too with extension function and kord builder
And I need to do that for each used Kord builder.
Instead of fix a equals & hashcode methods that don't work, I need to do that. That's a non sense ... It's preferable to fix the methods in the lib in my opinion
and how do you use these builders?
and do you use the kord builders in their dsl form? if not, why? 👀
I'm using Kord builder, and that's why I would like to fix the equals & hashcode
For example, I have a component like that:
So here, you see I'm using the kord builder
To create all needed row, it's this code:
(The builder store the components, lifecycle, in some order etc. in short, several things are managed in it
So when I render, I keep the last Kord InteractionResponseModifyBuilder and I would like to compare the last and the new rendering to not sending unnecessarily the data to Discord and minimize the network consumption
I don't know if it's understandabl
@LustigerLurch So I created the PR and hope that will be reasonable accepted 😂 https://github.com/kordlib/kord/pull/968
GitHub
fix: Implementation for Equals & Hashcode in Builder by Distractic ...
Context
When we compare the builder, like EmbedBuilder, the comparison between two instances will always return false no matter the field set. For example:
println(EmbedBuilder() == EmbedBuilder())...
and where in this code would having equals on the builders help?
In my project (private for the moment)
And I'm waiting this PR to continue 😅
Hello @LustigerLurch
I have an issue with my custom builder
When I put "null" has value for embed or components, the embeds or components are removed from the interaction.
Normally, it's when you put an empty list no?
If everything is null , I have the expected error
REST request returned an error: 400 Cannot send an empty message null
so no problems
but when I have 1 Component & null embeds, the embeds disapears in Discord interface ..
but the value "null" should mean "nothing change" no? otherwise if I went to remove the embeds I put a mutableList()
@gdude [he/him] Have you an idea about that too?Null should mean it isn't removed, yeah
well so I don't understand
Before update:
After update:
it uses an optional and nullable field internally. if the setter isn't called, it remains
Optional.Missing
, when you set it to null
, it'll be Optional.Null
. this maps to what the endpoint can do (optional and nullable parameters).aah so I need to set it to missing?
that's what i meant with optional and nullable values here btw
you can't, it's internal to the builder
you instead shouldn't touch it
Ok so I have an issue here
- First render:
embeds = list(..)
- Update (second render): No change in embeds, so embeds should be missing
Because if I don't set the embeds, the value will always be the first list(..)
so in the REST request, the body will contains the embeds fieldyou need to check for changes in the second render. if there aren't any, just don't set the properties of the kord builder, just like here
yes but, if I don't use the
setter
the value of builder will always be the first list(..)
no?
so .. the request body will always contain the list and not a missing propertythat's one reason why you shouldn't reuse builder objects
Well so, I should always send all structure of the message even if embeds doesn't have changes
if you use kord's dsl functions, you shouldn't even have to create builder instances yourself but just use them as a receiver in a lambda / extension function
no, a fresh builder will default to everything not required to be missing/null (whatever is allowed for a particular endpoint). so you just add what you need, use it for one request, and then let go of it.
is there a way to have the body request sent to discord in log?
trace level logs it
So I tried and seems that works
Reusing builders can actually be handy
The KordEx welcome extension has to figure out how and when to update messages and in that sense it uses fresh builders and does a ton of very annoying comparisons
it will look something like this:
I need to use logback with kotlin multiplatform? (Never did that with KMP)
logback avec kotlin multiplatform?
You can't, logback is jvm
Avec is "with" in French
what platform do you target? JVM or JS?
french word ah ah sorry
for JVM, you can use any slf4j implementation, for other platforms (JS for now) you need to use https://github.com/oshai/kotlin-logging
for my test JVM so yes I can use logback
ah yes this lib! I forgot
thanks
And how do you know that 🥲
Studied French for 8 years
😮
Don't remember most of it tho
ah 🥲
They teach it at school here
You can understand or not at all?
I can understand some of it
But this is off topic
they do here too, but i chose latin over french - idk why though xD
Why 🥲 We have course for Latin too, but everyone prefer escape this language
It's okay, all you had to do was say you hate yourself /lh