- Changed 'READ_MESSAGES' to 'VIEW_CHANNEL' to keep with Discord's API Docs
- Defaulted Guild.premium_subscription_count to 0 to stop error
- max_presences to 5,000 as Discord's API Suggest
- Added UserUpdate event for when the Client user is updated.
This commit cleans up a mess I created when I originally added the
`Guild.sync` functionality. The original intention of this function
was to provide a simple interface to ensuring the local state of a
guild was "up to date". This abstraction turned out to be a bad idea
for the following reasons;
- Its completely unclear what "sync" means in the context of a Guild.
Hiding the way syncing guild members works (which is a pretty "developer
unfriendly" as it is) just results in more confusion for very little
value.
- Discord technically supports sending multiple guild ids in a single
`REQUEST_GUILD_MEMBERS` op which this interface didn't support or
handle. Using this function as it was intended on a largeish bot would
result in your gateway client getting rate limited for quite a bit on
startup (which is lame).
- This implementation of guild member syncing resulted in a `synced`
flag on guilds, which is basically completely useless and doesn't mean
anything much at all (since REQUEST_GUILD_MEMBERS is purely async and
there is no correct way to confirm a request was fulfilled.
To cleanup this mess I've made the following changes;
- Entirely deprecate `Guild.sync`. This is just a bad function name and
should die in a fire to save our future children from pain and
frustration.
- Add `Guild.request_guild_members`. This function now properly conveys
what it does and provides a more correct interface to this Discord
functionality (nb: Guild.sync now calls this function, which does not
prevent multiple calls from firing requests).
- Add `GatewayClient.request_guild_members`. This function provides an
alternative interface for sending the request guild members op without
low-level GatewayClient interfacing. Ideally users who need to avoid
being rate limited and/or want better guild member syncing performance
can use this function which accepts multiple guild ids.
TL;DR;
- If you don't call `Guild.sync`; you don't need to worry about
anything.
- If you call `Guild.sync` anywhere at all and you don't really care
about the performance impact of syncing guild members one-by-one; just
change your code to call `Guild.request_guild_members`.
- If you call `Guild.sync` in a `GUILD_CREATE` handler or you care about
the performance impact of syncing multiple Guilds; move to using the
underlying GatewayClient interface and sync multiple guilds at once
(likely in batches).
* initial voice
* some updates
fixed it
* some style updates
replaced the speaking when joining with an actual client_connect event
* please pass
* replaced channel with client in VoiceData and VoiceSpeaking events
Also changed some voice sending stuff
* added more debug logs
* fixed version not being set on the voice gateway
* added voice_clients in state
Removed making a listener for voice state/server update for each voice connection, instead have only one listener and use the voice_clients in state to update based on that
Added priority speaking flag, also added some rtcp stuff, like a new event called 'RTCPData'
This update fixes some issues if you connect to another voice channel, instead of making a whole new voice connection, it just reuses one in the state.
* flake8 error fix
Discord is inconsistent here and doesn't emit a VoiceStateUpdate for the
old session_id when a user connects to voice from a different device
(thus disconnecting the first device). To avoid corrupting our voice
state cache, we need to remove any of the users old sessions (they
should have at most one).
I included tests on this one because its esoteric and undocumented, so
there is a high chance I'll break it in the future.
It's possible for Discord to send us presences for users which do not
actually exist in the Guild (remember; eventually consistent), so we
should throw these away when we get them.
There where various oddities and bugs here, namely:
- Guild kept its initial `presences` list even though this is basically
useless, and was never kept up-to-date
- State did not properly use all the fields of presence_update, and was
creating some annoying recursive oddities w/ user and presence binding
GUILD_UPDATES are cool and special and of course they are partial.
Although this is logical, our type/models autoinitialize some fields by
default (which is actually fairly sane). However when this happens, we
smash these new blank mappings over the previously updated state.
Instead we should just ignore fields that don't come in GUILD_UPDATEs,
and save our state.
- Add support for attachments and message embeds
- Fix commands being weirdly stored by some key (which doesn't make
sense)
- Added CommandEvent.codeblock which represents the first codeblock in
the message (useful for eval like commands)
- Cleanup the spawn utilties on plugin a bit
- Fix GuildBanAdd/GuildBanRemove
- Unset model fields are now a special sentinel value
- etc stuff
Tl;dr we now use __slots__ in a bunch of places. This could still be
better, and we do a bit too much magic in the modeling to make me happy.
But thats for later, for now we're going from ~250mb on 2500 guilds to
~160mb.
- Allow configuring the state module within the normal configuration
(under the 'state' key)
- Rate limit events being sent on the gateway socket
- Convert to using lazy_datetime in a bunch of places
- Allow configuring guild member sync
- Better logic around loading guilds, add State.ready condition which
can be waited on
- Fix inheritance in the modeling framework (how was this not working
before lol wut)
- Added __slots__ to a bunch of low-hanging fruit models
- Move member sync onto the guild object as Guild.sync()
- Convert to Dannys CachedSlotProperty (could still be better, will
improve later)
- Added util.snowflake.calculate_shard
The biggest part of this commit is a plugin storage subsystem, which at
this point I'm fairly happy with. I've iterated on this a couple times,
and the final result has a very clean/simple interface, is easy to
extend to different data stores, and has a very few minimal number of
grokable edge cases.
- Storage subsytem
- Fix command group abbreviations
- Fix reconnecting in the GatewaySocket
- Add pickle support to serializer
* Minor spelling fixes
* Minor spelling fixes
* Minor spelling fixes
* Minor spelling fixes
* Minor spelling fixes
* Minor spelling fixes
* Minor spelling fixes
- Storage backends take a config
- Add command permissions
- Add ability to listen to BOTH incoming and outgoing gateway packets
- Heavily refactor cli, now prefer loading from config with options as
overrides
- Add debug function to gateway events, helps with figuring data out w/o
spamming console
- Change Channel.last_message_id from property that looks in the message
tracking deque, to a attribute that gets updated by the state module
- Add State.fill_messages for backfilling the messages store
- Handle MessageDeleteBulk in State
- Add some helper functions for hash/equality model functions
- Fix MessageIterator
- Add Channel.delete_message, Channel.delete_messages
- Some more functional stuff
- Snowflake timestamp conversion
- Bump holster
- s/DiscoClient/Client (was redundant and looked ugly)
- move cached_property to functional utils
- abstract client configuration out to a ClientConfig
- command line utility is now completely isolated from the client
- add ETF (using erlpack) support, optionally enabled via command line
flags (and only works on 2.x because of erlpack)
- Refactor the way gateway events are built a bit
- Add documentation on utilities