Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ComponentsV2 support #3123

Open
wants to merge 204 commits into
base: next
Choose a base branch
from
Open

Conversation

jamesbt365
Copy link
Member

@jamesbt365 jamesbt365 commented Feb 21, 2025

Opened early, but getting a PR open sooner rather than later doesn't hurt.

TODO:

  • Base typing
  • Test thoroughly to make sure everything deserializes
  • Assure that I'm typing this correctly and not making things vague where it shouldn't be
  • Make Component & others more resilient to discord changes
    • Right now any change discord makes to components could knock out our Message deserialization.
  • Mark under unstable feature flag
    • This is still getting breaking changes and we should wait until rollout before marking this as stable.
  • Use FixedString everywhere relevant.
  • Add relevant builders
  • Document, including updating limits.

Additionally, we really need to PR to current and modify the deserialization to not fail if the top level component is not an ActionRow or it will not deserialize. (See #2963) (Done in #3127)

Once merged, as usual a PR to poise@serenity-next to add support over there too!

Sorry, something went wrong.

@jamesbt365 jamesbt365 added enhancement An improvement to Serenity. discord feature Related to Discord's functionality. labels Feb 21, 2025
@github-actions github-actions bot added model Related to the `model` module. examples Related to Serenity's examples. builder Related to the `builder` module. collector Related to the `collector` module. labels Feb 21, 2025
@jamesbt365 jamesbt365 force-pushed the components-v2 branch 2 times, most recently from 59f40fd to 778ab88 Compare February 27, 2025 01:22
@github-actions github-actions bot removed the examples Related to Serenity's examples. label Feb 27, 2025
@jamesbt365 jamesbt365 marked this pull request as ready for review February 28, 2025 16:08
@jamesbt365
Copy link
Member Author

Clippy failure does not seem like my fault? But this should be complete now.

@jamesbt365
Copy link
Member Author

I forgot the new field for webhooks, will add later.

@jamesbt365
Copy link
Member Author

I forgot the new field for webhooks, will add later.

Seems like this applies prior to ComponentsV2 too, though the restriction here is that they can only use non-interactive components on non application owned webhooks when sending this query param.

This can be implemented separately as this works on link buttons from my understanding and the information on https:discord/discord-api-docs#7368.

So... this PR should be done completely and now just needs a review (and fixing whatever funky stuff is going on with our CI?)

GnomedDev and others added 17 commits March 7, 2025 12:41
…erenity-rs#2646)

This avoids having to allocate to store fixed length (replaced with normal
array) or fixed capacity (replaced with `ArrayVec`) collections as vectors for
the purposes of putting them through the `Request` plumbing.

Slight behavioral change - before, setting `params` to `Some(vec![])`
would still append a question mark to the end of the url. Now, we check
if the params array `is_empty` instead of `is_some`, so the question
mark won't be appended if the params list is empty.

Co-authored-by: Michael Krasnitski <42564254+mkrasnitski@users.noreply.github.com>
These are unnecessary. Accepting `impl Into<Arc<T>>` allows passing either `T` or `Arc<T>`.
This trades a heap allocation for messages sent along with thread
creation for `Message`'s inline size dropping from 1176 bytes to 760
bytes,
…l models (serenity-rs#2656)

This shrinks type sizes by a lot; however, it makes the user experience slightly
different:

- `FixedString` must be converted to String with `.into()` or `.into_string()`
  before it can be pushed to, but dereferences to `&str` as is.
- `FixedArray` must be converted to `Vec` with `.into()` or `.into_vec()`
  before it can be pushed to, but dereferences to `&[T]` as is.

The crate of these types is currently a Git dependency, but this is fine for
the `next` branch. It needs some basic testing, which Serenity is perfect for,
before a release will be made to crates.io.
…enity-rs#2668)

This commit:

- switches from `u64` to `i64` in `CreateCommandOption::min_int_value` and
`CreateCommandOption::max_int_value` to accommodate negative integers in
Discord's integer range (between -2^53 and 2^53). Values outside this
range will cause Discord's API to return an error.
- switches from `i32` to `i64` in `CreateCommandOption::add_int_choice` and
`CreateCommandOption::add_int_choice_localized` to accommodate Discord's
complete integer range (between -2^53 and 2^53). Values outside this
range will cause Discord's API to return an error.
This cache was just duplicating information already present in `Guild::members`
and therefore should be removed.

This saves around 700 MBs for my bot (pre-`FixedString`).

This has to refactor `utils::content_safe` to always take a `Guild` instead
of`Cache`, but in practice it was mostly pulling from the guild cache anyway
and this means it is more likely to respect nicknames and other information,
while losing the ability to clean mentions from DMs, which do not matter.
`Embed::fields` previously had to stay as a `Vec` due to `CreateEmbed` wrapping
around it, but by implementing `Serialize` manually we can overwrite the
`Embed::fields` with a normal `Vec`, for a small performance hit on
serialization while saving some space for all stored `Embed`s.
Simply missed these when finding and replacing.
This uses the `bool_to_bitflags` macro to remove boolean (and optional boolean)
fields from structs and pack them into a bitflags invocation, so a struct with
many bools will only use one or two bytes, instead of a byte per bool as is.

This requires using getters and setters for the boolean fields, which changes
user experience and is hard to document, which is a significant downside, but
is such a nice change and will just become more and more efficient as time goes
on.
…rs#2681)

This swaps fields that store `Option<Int>` for `Option<NonMaxInt>` where the
maximum value would be ludicrous. Since `nonmax` uses `NonZero` internally,
this gives us niche optimisations, so model sizes can drop some more.

I have had to include a workaround for [serenity-rs#17] in `optional_string` by making my
own `TryFrom<u64>`, so that should be removable once that issue is fixed.

[serenity-rs#17]: LPGhatguy/nonmax#17
A couple of clippy bugs have been fixed and I have shrunk model
sizes enough to make `clippy::large_enum_variant` go away.
A discord bot library should not be using the tools reserved for low
level OS interaction/data structure libraries.
xacrimon and others added 10 commits March 7, 2025 13:03
…3111)

As the title notes, this commit replaces fxhash for foldhash as used in the
cache. dashmap, due to it's sharding, has to share entropy with what's handed
down to internal maps. Since `hashbrown` and by extension `std` use various
sections of the high bit range for special grouping & sorting, dashmap is left
with the only option to shard on low bits.

This, however, presents problems, because fxhash outputs hashes of very bad
quality, with only the high bits having any real entropy. This was probably a
solid choice back in 2018 when we lacked other good fast alternatives. But
since then `ahash` matured and we've had significant research and development
in "good enough" hashing for datastructures with short keys, [the most recent
step forward coming from a rather well known face][foldhash]. This improves
shard selection quite a bit and reduces contention significantly. Using fxhash
in a dashmap specific benchmark causes contention to go up by 3-8x when keys
are k-sortable with time (Discord snowflakes) on an M1 Pro.

[foldhash]: https://github.com/orlp/foldhash
…s#3088)

This replaces the time unit that determines how many messages in a
period of X time should be deleted when a user is banned. Discord
expresses this time in seconds, whereas Serenity exposed it in days. The
limit is still 7 days, but with this, users of Serenity can be more
precise with which messages they want to delete.
…ap tree (serenity-rs#3114)

Avoid temporarily deserializing gateway messages to a `serde_json::Map<String,
Value>` before typed deserialization to an `Event`. 

Previously, this meant the creation of a `serde_json::Value` tree, causing
creation and immediately after the destruction of upwards of hundreds to
thousands of owned strings and btreemaps for every handled gateway event.
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
If the last batch to be started was not of maximum size, it wouldn't get popped
off the queue. Instead, we should just pop off the queue periodically to ensure
that we fully flush it. 

On client startup, we queue all shards before popping the first batch, so
suboptimal batch sizes are not a concern. Now, the queue also doesn't have to
worry about "concurrent mode" and saturating the size of its batches.
Running `cargo fix --edition` produces a lot of noise, and the relative
drop order change shouldn't affect us because we don't use any unsafe
code. What I did was manually change the edition and then just fix the
compiler errors.
This was undocumented and done twice. Let's just get rid of it as users had to
use the `serenity::util` function if they were following the documentation
anyway.
So... yeah, not under `unstable` yet but things are just starting to work!

Need to refactor some old component stuff, and when i put this under the
unstable feature I've got some code duplication to handle.

Going well so far, sections work great and are really extensive
I do need to look at resolved media stuff, as right now i don't handle
that.
@jamesbt365
Copy link
Member Author

rebased for review reasons, but due to a timecrunch i haven't added V2 support on webhooks yet, will do in a couple hours when i get back.

@jamesbt365
Copy link
Member Author

rebased for review reasons, but due to a timecrunch i haven't added V2 support on webhooks yet, will do in a couple hours when i get back.

Disregard this comment, i didn't have time to properly check but what was needed was added cleanly in the rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
builder Related to the `builder` module. collector Related to the `collector` module. discord feature Related to Discord's functionality. enhancement An improvement to Serenity. model Related to the `model` module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet