NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #4799 most downloaded on crates.io
Procedural macros for command creation for the Serenity library.
Last release 9 months ago
20 Dec 2025
Release timing varies
gaps range from 4 weeks to 1.1 years
Most releases are documented
notes for 16 of 25 stable releases
1 version withdrawn
withdrawn after publishing
7 years old
32 releases · first in 2019
Thanks to the following for their contributions:
Thanks to the following for their contributions:
Message::member structfield ([@zeyla]) [c:0e1e8fb]Mentionable for CurrentUser ([@zeyla]) [c:4a24c90]From<CurrentUser> for User and
From<&CurrentUser> for User ([@zeyla]) [c:af7f176]Args docs ([@acdenisSK]) [c:2603063]Message::mentions_user_id, Message::mentions_user
([@Lakelezz]) [c:1162e68]Member::highest_role_info ([@zeyla])
[c:c659bbd]str::match_indices for some Args ops ([@acdenisSK])
[c:cc6b567]if length == 1 branch in Args functions ([@acdenisSK])
[c:6346975]Args::find, Args::find_n ([@acdenisSK]) [c:5ba521b]Args from the ground up ([@acdenisSK]) [c:ff9edc0]One column per quarter.
Thanks to the following for their contributions:
Thanks to the following for their contributions:
Date header into account when ratelimiting ([@zeyla])
[c:40db3c0]This release contains the usual bugfixes and helper methods.
This release contains the usual bugfixes and helper methods.
Thanks to the following for their contributions:
CreateEmbed method parameters ([@acdenisSK])
[c:f115c17]unrecognized_command method ([@Lakelezz]) [c:2937792]EventHandler ([@acdenisSK]) [c:80dfcb0]Drop impl for ffmpeg container ([@FelixMcFelix]) [c:3d67a4e]content_safe ([@megumisonoda]) [c:2ab714f]Args input is empty ([@acdenisSK])
[c:beebff5]CreateEmbed and CreateMessage consistent ([@acdenisSK])
[c:77c399b]help command precedence ([@acdenisSK]) [c:c6a5fe4]Args::is_empty behaviour ([@acdenisSK]) [c:e5bcee7]Args::full_quotes ([@acdenisSK]) [c:24d2233]AuditLogEntry::target_id ([@acdenisSK])
[c:0d779ba]AuditLogOptions to be correct types ([@acdenisSK], [@jkcclemens]) [c:217e1c6], [c:2791ed7]CreateEmbed builder methods
([@xentec], [@acdenisSK], [@zeyla]) [c:2e1eb4c] [c:d8c9d89], [c:a4cc582],
[c:ffc5ea1]no_run to doctests that instantiate a Client
([@Roughsketch]) [c:003dc2e]Args ([@acdenisSK]) [c:b9fa745]This release contains a number of fixes, a few more model helper methods, and additional framework features.
This release contains a number of fixes, a few more model helper methods, and additional framework features.
Thanks to the following for their contributions:
CreateCommand ([@acdenisSK]) [c:d193975]Message::member ([@zeyla]) [c:ce2952a]delete_messages ([@zeyla]) [c:92c91b8]Into<Option<Box<T>>> bound ([@zeyla]) [c:eee3168]This release is a rewrite of the client and gateway internals with a minimal amount of breaking changes for userland code. These changes are mainly to…
This release is a rewrite of the client and gateway internals with a minimal amount of breaking changes for userland code. These changes are mainly to prepare for Tokio and to reduce the number of atomic operations per received event, reducing the number of atomic operations by roughly 85%. The framework has also seen a rewrite, and is now centered around a trait-based design.
Thanks to the following for their contributions:
Per [c:91c8ec4], the Guild::default_channel and
Guild::default_channel_guarenteed methods now return
Option<Arc<Mutex<GuildChannel>>> instead of Option<GuildChannel>. This
avoids a clone. To access the channel, you just have to retrieve a read or write
lock by doing guild.default_channel()?.read() or
guild.default_channel()?.write().
Per [c:14b9222], there is a new Member::default_channel() function that
returns the default channel for the user. This no longer returns the channel
with the same ID as the guild itself, as this behaviour was changed by Discord.
A member's "default channel" is now the top-most channel that it has permission
to view. Accordingly, Guild::default_channel matches this behaviour.
Per [c:93e0a42], the library now uses the parking_lot crate's Mutex and
RwLock implementations over the stdlib's. parking_lots implementations are
more efficient, do not poison due to lock drops on unwinding, and implement
eventual fairness.
To account for this, change all Mutex lock retrievals and RwLock read and
write lock retrievals to not unwrap. parking_lot's Mutex::lock,
RwLock::read, and RwLock::write don't return Results, unlike the stdlib's.
Per [c:78c6df9], the Guild::features structfield is no longer a
Vec<Feature>. Discord adds guild features over time, which can cause guilds
with those new features to fail in deserialization. Instead, we're
future-proofing by making this a Vec<String>.
Per [c:65e3279], the CreateEmbed builder's field and fields functions no
longer take a builder as the argument, and instead take 3 arguments. For
example, code like this:
channel.send_message(|m| m
.embed(|e| e
.title("This is an embed")
.field(|f| f
.name("Test field")
.value("Test value")
.inline(true))));
Would now be this:
channel.send_message(|m| m
.embed(|e| e
.title("This is an embed")
.field("Test field", "Test value", true)))
Per [c:ad0dcb3], shards can no longer have their afk property set, as this was
a leftover from user account support. This removes the afk parameter of the
Context::set_presence function, removal of the parameter from the
Shard::set_presence function, and the Shard::set_afk function.
Per [c:b328b3e], the client::EventHandler no longer prefixes all trait methods
with on_. An implementation that looks like this:
use serenity::client::{Context, EventHandler};
use serenity::model::Message;
struct Handler;
impl EventHandler for Handler {
fn on_message(&self, _: Context, msg: Message) {
// ...
}
}
Now looks like this:
use serenity::client::{Context, EventHandler};
use serenity::model::channel::Message;
struct Handler;
impl EventHandler for Handler {
fn message(&self, _: Context, msg: Message) {
// ...
}
}
(a note on the serenity::model::channel::Message import later.)
Per [c:b19b031], Client::new returns a Result, as it now creates some
essential information on instantiation instead of deferring it to when a
connection is started. You can probably just unwrap this Result.
Per [c:b8efeaf], [c:d5a9aa8], and [c:65233ad], the client and gateway internals
have been rebuilt to significantly reduce the number of atomic operations
(upwards of ~85%). This means that retrieval of shard information (like the
shard latency to the Discord gateway or the current connection status) are
retrieved via the encompassing ShardManager located on
the client. This can be inserted into the client's data structfield if you
need to access that information in event or framework command handlers. See
this example for more information. Additionally,
Context::quit to shutdown the shard no longer exists; go through the
ShardManager instead.
Per [c:aad4744], the framework's Args::list function has been renamed to
Args::multiple for consistency.
Per [c:f10b9d7], [c:1fd652b], [c:0aa55a2], the framework has been reworked to be trait-based; thus as per [c:f61816c], [c:4e20277], allowed more useful functionality to commands.
Per [c:05f6ed4], the client's close handle has been removed, in favour of
doing so through the ShardManager.
Per [c:8c9baa7], the Guild::default_message_notifications, Guild::mfa_level,
PartialGuild::default_message_notifications, and PartialGuild::mfa_level
structfields are now enums to represent a stronger type, instead of u64s.
Per [c:bcd16dd], the model module has been broken up: instead of a giant root
module full of imports, types have been moved to where they fit. For example,
the Message, Reaction, and Channel structs are now in the model::channel
module. The RichInvite, Member, Role, and MfaLevel types are now in
model::guild. Refer to the commit message or the
model module docs for more information.
Per [c:be43836], the http::HttpError enum's InvalidRequest variant no longer
gives just the HTTP status code of the response. It now includes the full
Response instance.
Per [c:2edba81], the builder re-export in the utils module no longer exists
after being there in deprecation for a long time. Please import it like so:
// old
use serenity::utils::builder;
// new
use serenity::builder;
ConnectionStage derive Copy ([@acdenisSK]) [c:551f166]Vec<T> parameter with more generic
IntoIterator<Item=T> ([@ftriquet]) [c:b146501], [c:934eb3a]AsRef ([@acdenisSK]) [c:e0e7617], [c:b62dfd4]impl BanOptions for &str ([@acdenisSK]) [c:7c911d5]Default on IDs and CurrentUser ([@acdenisSK]) [c:0881e18]str::parse if parse_username fails ([@acdenisSK])
[c:8c85664]RoleId ([@acdenisSK]) [c:5d4301b]Command::aliases public ([@acdenisSK]) [c:8c83866]impl FromStr for ReactionType ([@acdenisSK]) [c:2032a40],
[c:84706f1]Into<String> to Display
([@acdenisSK]) [c:05dad71]Debug on more public types
([@thelearnerofcode]) [c:e5a6f3a]PrivateChannel::say to accept a more generic argument
([@fenhl]) [c:a359f77]impl From<EmojiId, EmojiIdentifier> for ReactionType ([@fenhl])
[c:68156c9]impl From<&Path> for AttachmentType ([@zeyla]) [c:7a5aa3c]GameType::Listening ([@hsiW], [@zeyla]) [c:40c5c12], [c:a17fea7]cmd function to CreateCommand and CreateGroup
([@acdenisSK]) [c:e748d1f]Reaction::message function ([@Roughsketch]) [c:fd19446]Reaction::channel function ([@zeyla]) [c:e02a842]Reaction::user function ([@zeyla]) [c:82b87f1]Deserialize for {,Gateway,Voice}Event ([@zeyla])
[c:c3aa63f]help() to CreateGroup ([@Lakelezz]) [c:39a1435]before/after middleware to Command ([@acdenisSK])
[c:4e20277]try_opt! macro to using ? operator ([@hsiW])
[c:2d23d8b]VIEW_AUDIT_LOG permission ([@Lakelezz]) [c:612e973]str::parse on ChannelId FromStr impl ([@acdenisSK])
[c:0525ede]Guild ([@zeyla]) [c:3d24033], [c:99d17d2],
[c:2abeea5]Args::len ([@acdenisSK]) [c:2c9b682], [c:b60d037],
[c:143fddd]Channel ([@timotree3]) [c:f0a56f4]animated field to Emoji and ReactionType ([@zeyla])
[c:f2fa349]Args ([@Lakelezz])
[c:62647f5]Region to include new voice regions ([@Flat]) [c:d264cc3]Args::iter_quoted ([@acdenisSK]) [c:032c5a7]num implementations on models ([@zeyla]) [c:0b1f684]serde::Serialize on all models ([@zeyla])
[c:25dddb6]reaction_users' after parameter ([@zeyla])
[c:85d7d5f]Member::highest_role ([@zeyla]) [c:b7542f4]Guild::greater_member_hierarchy ([@zeyla]) [c:84ff27b]webhook_id a majour parameter in ratelimiting ([@zeyla])
[c:1735e57]multiple_quoted ([@Lakelezz]) [c:9aad1aa]# finding in Guild::member_named ([@tahahawa]) [c:a7b67df]impl Form<Embed> for CreateEmbed
([@drklee3]) [c:9aaa555]Shard::latency, avoiding panics ([@zeyla])
[c:08db9fa]correct roles checks in help commands ([@Lakelezz])
[c:470f366]Guild::{default_channel, default_channel_guarenteed} now return
an Arc<Mutex<GuildChannel>> instead of a clone of the channel ([@acdenisSK])
[c:91c8ec4]" " ([@jhelwig])
[c:3a4cb18]default_channel to match Discord's new
behaviour ([@hsiW]) [c:14b9222]I from being user-implemented
([@acdenisSK]) [c:7cf1e52]parking_lot::{Mutex, RwLock} ([@zeyla]) [c:93e0a42]{Guild, PartialGuild}::features a Vec<String> ([@zeyla])
[c:78c6df9]&'static strs and
a VecMap ([@acdenisSK], [@zeyla]) [c:9908999], [c:3a0c890], [c:26fe139]CreateEmbed::field{,s} to not take builders ([@zeyla])
[c:65e3279]afk field ([@zeyla])
[c:ad0dcb3]on_ prefix to EventHandler tymethods ([@zeyla])
[c:b328b3e]Args::list -> Args::multiple ([@acdenisSK]) [c:aad4744]Guild and PartialGuild structfields
([@zeyla]) [c:8c9baa7]builder module re-export ([@zeyla]) [c:2edba81]is_bot state boolean ([@zeyla]) [c:524b8f8]InterMessage enum to
communicate over the gateway ([@zeyla]) [c:9232b8f]Error's Display impl ([@zeyla]) [c:ee2bbca]Reaction::{message, users} methods hit the API
([@zeyla]) [c:141bbfc]ToString blanket impl for Displays ([@acdenisSK])
[c:3ca7e15]Args::parse_quotes ([@zeyla]) [c:60613ef]Client::new ([@zeyla]) [c:25d79ac]User ([@Lakelezz]) [c:9da642a]User::has_role ([@zeyla]) [c:b52eb9f][model] Deprecate some methods on Channel ([@zeyla]) [c:23ff6f]
This release contains the regular bugfixes, new features and slight behaviour changes.
Thanks to the following people for their contributions:
PartialEq impls and doc-tests to Args ([@acdenisSK]) [c:f9e5e76]Args ([@acdenisSK]) [c:9428787]DispatchError ([@acdenisSK]) [c:a58de97]str::parse if utils::parse_username fails ([@acdenisSK]) [c:292ceda]User::has_role ([@zeyla]) [c:d3015a0ff]Context ([@zeyla]) [c:3616585]allow_whitespace ([@ConcurrentMarxistGC]) [c:e694766]help_commands.rs ([@Lakelezz]) [c:e02d5fb]delete_message if there's just one message to delete ([@acdenisSK]) [c:c7aa27d]ChannelType ([@acdenisSK]) [c:e57b510]Mutex and RwLock from the prelude ([@zeyla]) [c:74ec713]Cargo.toml to actually be v0.4.2 ([@Caemor]) [c:5829c67]Shard ([@efyang]) [c:fcc4e2c]Channel ([@zeyla]) [c:23ff6f]This release contains bugfixes and some newly added or newly exposed functionality.
This release contains bugfixes and some newly added or newly exposed functionality.
Thanks to the following for their contributions this release:
IntoIterator ([@ftriquet])[c:55167c3]IntoIterator ([@ftriquet]) [c:022e35d]Guild::members_starting_with ([@Lakelezz]) [c:b3aa441]Guild::members_containing ([@Lakelezz]) [c:1b167b5]impl<'a> BanOptions for &'a str ([@acdenisSK]) [c:cf40386]Default on CurrentUser and IDs ([@acdenisSK]) [c:09a8a44]Guild::members_username_containing, members_nick_containing
([@Lakelezz]) [c:002ce3a]Args ([@acdenisSK]) [c:0ed1972]has_all_requirements public ([@Lakelezz]) [c:08d390c]request_client! for attachment downloading ([@lolzballs])
[c:71f709d]User::tag and CurrentUser::tag discrim output ([@zeyla])
[c:6b9dcf5]initialized method purpose ([@acdenisSK]) [c:05f158f]to_owned -> to_string ([@acdenisSK]) [c:1bf4d9c]Args ([@acdenisSK]) [c:8572943]env_logger bot example [c:0df77b9]Member::roles ([@hsiW]) [c:8565fa2]try_opt! macro ([@hsiW]) [c:9b0c053]Per commit [c:ebc4e51], deprecated functions were finally removed. The following can simply have their usage renamed:
This release contains a lot of added functionality, minor-scale rewrites, bugfixes, documentation work, and the beginning of a rewrite to use the tokio ecosystem.
The release was delayed due to a [fairly majour bug][rust-websocket:issue:137] in rust-websocket that we have forked over to temporarily fix.
This release was lead in development by [@acdenisSK].
Thanks to the following for their contributions this release:
Per commits [c:af1061b], [c:cdedf36], and [c:aa307b1], Direct Messaging other bot users is now disallowed by the API. To fix this, simply don't do it.
Per commit [c:ebc4e51], deprecated functions were finally removed. The following can simply have their usage renamed:
Cache::get_channel --> Cache::channelCache::get_guild --> Cache::guildCache::get_guild_channel --> Cache::guild_channelCache::get_member --> Cache::memberCache::get_private_channel --> Cache::private_channelCache::get_role --> Cache::roleCache::get_user --> Cache::userChannelId::get_invites --> ChannelId::invitesChannelId::get_message --> ChannelId::messageChannelId::get_messages --> ChannelId::messagesChannelId::get_reaction_users --> ChannelId::get_reaction_usersChannelId::get_webhooks --> ChannelId::webhooksChannel::get_message --> Channel::messageChannel::get_messages --> Channel::messagesChannel::get_reaction_users --> Channel::reaction_usersClient::login_bot --> Client::newClient::login --> Client::newColour::get_b --> Colour::bColour::get_g --> Colour::gColour::get_r --> Colour::rColour::get_tuple --> Colour::tupleCurrentUser::distinct --> CurrentUser::tagGroup::get_message --> Group::messageGroup::get_messages --> Group::messagesGroup::get_reaction_users --> Group::reaction_usersGuild::get_bans --> Guild::bansGuild::get_channels --> Guild::channelsGuild::get_emoji --> Guild::emojiGuild::get_emojis --> Guild::emojisGuild::get_integrations --> Guild::integrationsGuild::get_invites --> Guild::invitesGuild::get_member --> Guild::memberGuild::get_members --> Guild::membersGuild::get_member_named --> Guild::member_namedGuild::get_prune_count --> Guild::prune_countGuild::get_webhooks --> Guild::webhooksGuildId::get_bans --> GuildId::bansGuildId::get_channels --> GuildId::channelsGuildId::get_emoji --> GuildId::emojiGuildId::get_emojis --> GuildId::emojisGuildId::get_integrations --> GuildId::integrationsGuildId::get_invites --> GuildId::invitesGuildId::get_member --> GuildId::memberGuildId::get_members --> GuildId::membersGuildId::get_prune_count --> GuildId::prune_countGuildId::get_webhooks --> GuildId::webhooksMessage::get_reaction_users --> Message::reaction_usersPartialGuild::get_bans --> PartialGuild::bansPartialGuild::get_channels --> PartialGuild::channelsPartialGuild::get_emoji --> PartialGuild::emojiPartialGuild::get_emojis --> PartialGuild::emojisPartialGuild::get_integrations --> PartialGuild::integrationsPartialGuild::get_invites --> PartialGuild::invitesPartialGuild::get_member --> PartialGuild::memberPartialGuild::get_members --> PartialGuild::membersPartialGuild::get_prune_count --> PartialGuild::prune_countPartialGuild::get_webhooks --> PartialGuild::webhooksPrivateChannel::get_message --> PrivateChannel::messagePrivateChannel::get_messages --> PrivateChannel::messagesPrivateChannel::get_reaction_users --> PrivateChannel::reaction_usersRole::edit_role --> Role::editUser::distinct --> User::taghttp::send_file has been replaced by http::send_files. Instead of using http::send_file like so:
use serde_json::Map;
use serenity::http;
use serenity::model::ChannelId;
use std::fs::File;
let channel_id = ChannelId(253635665344987136);
let filename = "mr-sakamoto.png";
let file = File::open(&format!("./img/{}", filename))?;
let map = Map::<String, Value>::new();
http::send_file(channel_id, file, filename, map)?;
Instead send an attachment of files, such as:
use serde_json::Map;
use serenity::http;
use serenity::model::ChannelId;
use std::fs::File;
let channel_id = ChannelId(253635665344987136);
let files = vec![
(File::open(&format!("./img/{}", filename))?, filename),
];
let map = Map::<String, Value>::new();
http::send_files(channel_id, files, map)?;
Similar logic can be applied to shortcut methods which have been removed, namely:
Channel::send_file (instead use Channel::send_files)ChannelId::send_file (instead use ChannelId::send_files)Group::send_file (instead use Group::send_files)GuildChannel::send_file (instead use GuildChannel::send_files)PrivateChannel::send_file (instead use PrivateChannel::send_files)Instead of using the now-removed Channel::delete_messages and
Channel::delete_permission, use the inner channel's method:
use serenity::model::{Channel, ChannelId};
let channel = ChannelId(253635665344987136).get()?;
let message_ids = vec![
MessageId(359845483356749825),
MessageId(359854838403694592),
];
if let Channel::Guild(c) = channel {
c.delete_messages(&message_ids)?;
}
Similar logic can be applied to Channel::delete_permission.
Member::find_guild ended up being only a shortcut to the Member::guild_id
structfield. Instead of calling the find_guild method like
member.find_guild(), instead access the structfield directly via
member.guild_id.
The model::permissions::{general, text, voice} methods have been removed, as
they ended up being shortcuts to the model::permissions::PRESET_GENERAL,
model::permissions::PRESET_TEXT, and model::permissions::PRESET_VOICE
constants, respectively.
Per commit [c:ea432af], event handling is now done via implementing a trait. Instead of passing functions to the client directly like:
use serenity::Client;
use std::env;
let mut client = Client::new(env::var("DISCORD_TOKEN")?);
client.on_message(|ctx, msg| {
// code
});
Instead implement the new EventHandler trait:
use serenity::client::{Client, Context, EventHandler};
use serenity::model::Message;
struct Handler;
impl EventHandler for Handler {
fn on_message(&self, ctx: Context, msg: Message) {
// code
}
}
let client = Client::new(env::var("DISCORD_TOKEN")?);
Per commit [c:4f2e47f], the deprecated ext module (which has recently only
been a series of re-exports for the cache, framework, and voice modules)
was removed. Instead of using serenity::ext::cache for example, use
serenity::cache.
Per commit [c:878684f], due to the concept of default channels being changed,
GuildId::as_channel_id has been deprecated due to the fact that the ID of the
default channel of a guild will no longer necessarily be the same as the guild's
ID.
If you require this same exact functionality (the GuildId as a ChannelId),
rewrite your code from:
use serenity::model::GuildId;
let channel_id = GuildId(81384788765712384).as_channel_id();
to:
use serenity::model::{ChannelId, GuildId};
let guild_id = GuildId(81384788765712384);
let channel_id = ChannelId(guild_id.0);
Per commits [c:2b053ea], [c:8cc2300], [c:8e29694], and [c:948b27c], custom frameworks can now be implemented, meaning that a built implementation is now passed instead of a base framework being provided and mutated. To use the old framework, modify code from:
use serenity::Client;
use std::env;
let mut client = Client::new(&env::var("DISCORD_TOKEN")?);
client.with_framework(|f| f
// method calls to mutate framework here
);
to the new style:
use serenity::client::{Client, EventHandler};
use serenity::framework::standard::StandardFramework;
use std::env;
struct Handler;
impl EventHandler for Handler { }
let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler);
client.with_framework(StandardFramework::new()
// method calls here to mutate framework here
);
Per commit [c:fc9eba3d], if you were pattern matching on the
serenity::framework::DispatchError::CheckFailed variant, instead either use or
ignore the matched data by rewriting code from:
use serenity::framework::DispatchError;
// Code to begin dispatch error handling here.
match dispatch_error {
DispatchError::CheckFailed => {
// Handle operation here.
},
// Other variants.
}
to:
// The standard implementation is now in a "standard" framework module, but
// that's unrelated.
use serenity::framework::standard::DispatchError;
match dispatch_error {
DispatchError::CheckFailed(_) => {
// Handle operation here.
},
// Other variants.
}
Per commits [c:45d72ef], [c:03b6d78], and [c:d35d719], the framework's
command! macro no longer parses arguments' types for you. You are now given an
Args struct that you can retrieve arguments from and parse from to a requested
type that implements FromStr.
For example, a simple sum function that looked like:
#[macro_use] extern crate serenity;
command!(sum(_ctx, msg, _args, x: i64, y: i64) {
let _ = msg.reply(&format!("Result: {}", x + y));
});
Now looks like:
use serenity::client::Context;
use serenity::framework::standard::Args;
use serenity::model::Message;
fn sum(_: &mut Context, msg: &Message, args: Args) -> Result<(), String> {
let x = match args.single::<i64>() {
Ok(x) => x,
Err(_) => return Ok(()),
};
let y = match args.single::<i64>() {
Ok(y) => y,
Err(_) => return Ok(()),
};
let _ = msg.reply(&format!("Result: {}", x + y));
}
Per commit [c:562ce49], serenity::model::User's FromStr implementation can
now hit the REST API. No code changes required, but do note the possibility.
Per commit [c:40031d9], the following routes have been removed for being userbot routes, which are leftovers from when serenity supported them and had them removed:
http::get_application_infohttp::get_applicationshttp::get_emojihttp::get_emojismodel::Guild::emojimodel::Guild::emojismodel::GuildId::emojimodel::GuildId::emojismodel::PartialGuild::emojimodel::PartialGuild::emojisPer commit [c:092f288], bitflags has been upgraded, which introduces a minor change in how to use permissions.
Update code from:
use serenity::model::permissions::{ADD_REACTIONS, MANAGE_MESSAGES};
foo(vec![ADD_REACTIONS, MANAGE_MESSAGES]);
to:
use serenity::model::Permissions;
foo(vec![Permissions::ADD_REACTIONS, Permissions::MANAGE_MESSAGES]);
CommandOrAlias and CommandGroup.commands
public ([@joek13]) [c:3db42c9]on_cached event ([@acdenisSK]) [c:6d6063f]is_new paramenter to the guild_create handler ([@acdenisSK])
[c:3017f6d]Guild::members_with_status ([@acdenisSK]) [c:a7a0945],
[c:29ee627]Ban and User impl Eq, Hash, and PartialEq
([@acdenisSK]) [c:64bfc54]BanOptions take and return an &str ([@acdenisSK]) [c:1ab8b31]{ChannelId, GuildChannel, PrivateChannel}::name functions
([@acdenisSK]) [c:ca0f113]CloseHandle derive Copy ([@blaenk]) [c:b249c82]nsfw property to channels ([@acdenisSK], [@Bond-009])
[c:b602805], [c:fd89d09], [c:fd47b86]Message::is_own ([@acdenisSK], [@zeyla]) [c:5a96724],
[c:fdbfbe0], [c:6572580]From<(u8, u8, u8)> for Colour ([@acdenisSK]) [c:6f147e1]Display bound instead of
&str ([@acdenisSK]) [c:7e913b6], [c:05162aa], [c:0810ab7]UserId::get ([@Roughsketch]) [c:bfdb57c]with_config{,_mut} ([@acdenisSK]) [c:1a08904]CreateCommand::num_args ([@Roughsketch]) [c:aace5fd]Context::handle ([@acdenisSK]) [c:97e84fe]MessageBuilder::push_mono_safeuse_quotes is active ([@acdenisSK]) [c:e7a5ba3]Reaction::name optional ([@acdenisSK]) [c:8f37f78]permissions::PRESET_GENERAL bits ([@zeyla]) [c:9f02720]ext module ([@acdenisSK]) [c:4f2e47f]GuildId::as_channel_id ([@acdenisSK]) [c:878684f]I bound for MessageBuilder language params ([@acdenisSK])
[c:f16af97]DispatchError::CheckFailed ([@Lakelezz])
[c:fc9eba3]FromStr parsing errors
([@acdenisSK]) [c:8bf77fa], [c:8d51ead]User's FromStr impl to hit REST ([@Roughsketch]) [c:562ce49]ModelError doctest ([@zeyla]) [c:bd9fcf7]EventHandler ([@acdenisSK]) [c:fdfd5bc]EventHandler changes ([@acdenisSK]) [c:511ec87]PrivateChannel::name ([@acdenisSK]) [c:14fd41b]match to an and_then ([@acdenisSK]) [c:5e5f161]Send + Sync bounds ([@acdenisSK]) [c:3c2716b]http::set_token ([@zeyla]) [c:cb18d42]Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
This release contains a number of added methods, fixes, deprecations, and documentation improvements. It brings a module restructure and an upgrade to…
This release contains a number of added methods, fixes, deprecations, and
documentation improvements. It brings a module restructure and an upgrade to
rust-websocket v0.20, hyper v0.10, and switching to native-tls, meaning
using an up-to-date rust-openssl v0.9 on Linux, schannel on Windows, and
Secure Transport on Mac. The long-standing issue [#56][issue:56] was closed.
Thanks to the following for their contributions this release:
Invite retrieval functions now accept a stats argument. If you don't need
stats, just pass false.
ChannelId::create_permission and GuildChannel::create_permission now accept
a reference, as they do not need to own the overwrite.
The deprecated GuildChannel methods (get_invites, get_message,
get_messages, get_reaction_users, get_webhooks) have been removed. Use
their equivalents without the get_ prefix.
The send_file functions have been deprecated. Use send_files instead by
passing a Vec.
CurrentUser::distinct and User::distinct have been deprecated. Instead use
CurrentUser::tag and User::tag.
User::get has been deprecated. Instead, use UserId::get.
Role::edit_role has been deprecated, renaming it to Role::edit.
time has been removed as a direct dependency, moving to chrono.
Public-facing fields that return time::Timespec or were a String in ISO-3339
format are now chrono::DateTime<UTC>s. Instead use its methods for what was
being done with the Timespecs or strings.
User::direct_message and User::dm now accept a builder to allow for more
complete, yet simple use out of the methods. Instead of passing a &str, use
the provided builder:
// old
user.dm("hello")?;
// new
user.dm(|m| m.content("hello"))?;
Client::login has been deprecated. Instead use Client::new:
use serenity::Client;
use std::env;
// old
let client = Client::login(&env::var("DISCORD_TOKEN")?);
// new
let client = Client::new(&env::var("DISCORD_TOKEN")?);
Member::guild_id is now no longer an Option<GuildId> -- just a GuildId.
Since this is now always present, Member::find_guild has been deprecated since
the cache now never searches the cache for the guild ID.
The deprecated GuildChannel methods get_invites, get_message,
get_messages, get_reaction_users, and get_webhooks have been removed. Use
their alternatives, such as GuildChannel::invites, instead.
GuildChannel::permissions_for [c:6502ded]Invite::url(), RichInvite::url() [c:3062981]VerificationLevel::Higher [c:7dbae6b]CurrentUser::invite_url ([@Roughsketch], [@Flat]) [c:e033ff3],
[c:0b95db9]impl From<char> for ReactionType [c:2afab7c]_line + _line_safe methods to MessageBuilder ([@Roughsketch])
[c:543b604]CurrentUser ([@Roughsketch]) [c:921f7f4]Content for MessageBuilder ([@eLunate]) [c:060b06e]User::refresh [c:8c04d31]Message::channel() [c:063a52f]CurrentUser::default_avatar_url [c:2d09152]CurrentUser::face(), User::face() [c:d033909]Member::permissions [c:39a28d3] ([@acdenisSK])wait parameter to http::execute_webhook [c:dc73d1a]@everyone role when checking channel overwrites ([@Roughsketch])
[c:b468cbf]unreachable_code lint in command! macro ([@Flat]) [c:eb43b9c]send_file deserialization [c:0102706]create_permission to take a reference [c:aea9885]GuildChannel methods [c:ab7f113]Guild::create_channel doesn't require mutability [c:494cc50]*User::distinct, add *User::tag [c:6579b1f]User::get [c:afc571f]Role::edit_role, add Role::edit [c:c00f349]User::direct_message/User::dm accept a builder [c:11a02db]Client::login, add Client::new [c:7990381]Member::guild_id non-optional [c:b4bd771]Context::channel_id and Context::queue [c:8b504ad]dynamic_prefix accept an &Message [c:2845681]Channel::delete_messages, Channel::delete_permission [c:7fc49d8]Message::nonce a serde_json::Value [c:c832009]login_bot usage from docs ([@hsiW]) [c:ae395f4]VoiceManager::join in example 06 ([@barzamin]) [c:6853daf]CreateGroup docs to the struct [c:71f3dbb]cookie dependency [c:92f4ec2]#[doc(hidden)] to pub(crate) [c:32e07e4] ([@acdenisSK])Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Deprecate methods prefixed with get_ [c:3f03f9a]
This is a very large release with a number of rewritten components. The cache
has been rewritten to make use of memory more efficiently, the models directory
has been re-organized, structures are now deserialized via serde and
serde_derive - instead of the custom decoding build script we had - with a
number of bugfixes and other various changes and additions.
Thanks to the following for their contributions this release:
Replace uses of ext::cache::ChannelRef with model::Channel.
The following ext::cache::Cache method signatures are now encased in
Arc<RwLock>s and should be handled appropriately:
callchannelguildguild_channelgroupmemberroleuserAdditionally, GuildId::find and UserId::find now return
Option<Arc<RwLock>>s.
Member::display_name now returns a Cow<String> instead of a &str.
client::Context has had most of its methods removed. The methods were mostly
a copy of those on ChannelId. Upgrade by instead calling methods on
ChannelId:
command!(foo(ctx) {
let _ = ctx.say("hello");
});
// is now written as:
command!(bar(_ctx, msg) {
let _ = msg.channel_id.say("hello");
});
CreateMessage::nonce has been removed. Instead, simply do not provide a nonce.
ChannelId::edit_message now has an argument signature of:
&self, message_id: M, f: F
where F: FnOnce(CreateMessage) -> CreateMessage, M: Into<MessageId>
instead of
&self, message_id: M, text: &str, f: F
where F: FnOnce(CreateEmbed) -> CreateEmbed, M: Into<MessageId>
To account for this change, modify code like so:
channel_id.edit_message(message_id, "new content", |e| e);
// now:
channel_id.edit_message(message_id, |m| m.content("new content"));
Message::edit has also had an argument signature updated to:
&mut self, f: F where F: FnOnce(CreateMessage) -> CreateMessage
from:
&mut self, new_content: &str, embed: F where F: FnOnce(CreateEmbed) -> CreateEmbed
To account for this change, modify code like so:
message.edit("new content", |e| e.description("test"));
// now:
message.edit(|m| m.content("new content").embed(|e| e.description("test")));
client::rest::accept_invite, Invite::accept, and RichInvite::accept have
been removed. Instead, do not attempt this, as they were userbot functions.
Selfbot support has been completely removed. Review the [commit message][c:d9118c0] for the long list of details.
Group calls and guild sync have [also been removed][c:c74cc15]. Read the commit message for all the details.
Instead of defining multiple separate error messages for command framework message dispatches, match the dispatch error in a single method:
// old code:
client.with_framework(|f| f
.configure(|c| c
.command_disabled_message("The command `%command%` was disabled")
.blocked_guild_message("The owner of this guild has been blocked")
.invalid_permission_message("You don't have permission to use this command")));
// new code:
client.with_framework(|f| f.on_dispatch_error(|_, msg, err| {
match err {
DispatchError::CommandDisabled(command_name) => {
let _ = msg.channel_id.say(&format!("The command `{}` was disabled", command_name));
},
DispatchError::BlockedGuild => {
// this change also allows for more intelligent error messages:
if let Some(guild) = msg.guild() {
let owner_id = guild.read().unwrap().owner_id;
if let Some(user) = CACHE.read().unwrap().user(owner_id) {
let c = format!("The owner - {} - has been blocked", user.name);
let _ = msg.channel_id.say(&c);
return;
}
}
let _ = msg.channel_id.say("The owner of this guild has been blocked");
},
DispatchError::LackOfPermissions(_) => {
let _ = msg.channel_id.say("You don't have permission to use this command");
},
}
}));
All functions prefixed with get_ have had the prefix removed. For example,
Guild::get_webhooks() is now Guild::webhooks().
Instead of using model::permissions::general(), model::permissions::text(),
and model::permissions::voice(), use
model::permissions::{PRESET_GENERAL, PRESET_TEXT, PRESET_VOICE}.
say method to Group, GuildChannel, PrivateChannel [c:a0bb306]send_file/send_message impls [c:bad9ac3]Message::guild [c:9ef5522]From<&str> for ReactionType [c:e7110ad]is_nsfw check to channels [c:9268f9c]Member::kick helper [c:83b1d96]Eq, Hash, PartialEq on ReactionType [c:86a4e00] ([@acdenisSK])joined_at values [c:cd914f5][0, 1] shards [c:f0d1157]Route::None routes [c:5bf6c2d]dynamic_prefix result [c:9ec05e7] ([@Roughsketch])Context methods [c:585af23]get_ [c:3f03f9a]User.discriminator a u16 [c:0f41ffc]Nothing published for this version
Nothing published for this version
This is a release to fix broken nightly builds, due to a change in how rustc handles lifetimes, with a few performance optimizations and other fixes.
This is a release to fix broken nightly builds, due to a change in how rustc handles lifetimes, with a few performance optimizations and other fixes.
For Group::send_message, PrivateChannel::send_message,
and GuildChannel::send_message, instead of passing in only a &str of
content, use a CreateMessage builder:
// assuming a `channel` is bound
// old signature:
channel.send_message("hello");
// new signature:
channel.send_message(|m| m.content("hello"));
Instead of calling message_id.get_reaction_users and passing in a ChannelId,
call channel_id.get_reaction_users and pass in the MessageId. Note that the
latter already existed.
// assuming `channel_id`, `message_id`, and `reaction_type` are bound
// removed method:
message_id.get_reaction_users(channel_id, reaction_type, Some(10), None);
// alternative method:
channel_id.get_reaction_users(message_id, reaction_type, Some(10), None);
status user setting for user accounts (e.g. online, invisible)
[c:0b9bf91]EditGuild to transfer ownership [c:f00e165]command! macro [c:97f9bd1]MessageId::get_reaction_users [c:268f356]GLOBAL ratelimit mutex a unit (opt.) [c:55ccaca]This is a general release for pretty much everything, from new features to bugfixes to a switch to a more OOP style. The current minimum supported ver
This is a general release for pretty much everything, from new features to bugfixes to a switch to a more OOP style. The current minimum supported version is rustc 1.13+.
The next release will be v0.2.0, which will feature serde codegen support along with a rewrite of the framework. It will be a more modularized version of the library. v0.2.0 will require rustc 1.15+, due to the stabilization of Macros 1.1.
Thanks to the following for contributions this release:
Two of the major highlights of this release are that the broken pipe issue has
been fixed, and the library is more OOP now and therefore no longer relies on
the Context to get stuff done. The methods feature flag has been removed.
When formatting using Display for ChannelIds, RoleIds, and UserId,
instead of formatting use their Mentionable equivilants:
use serenity::model::{ChannelId, RoleId, UserId};
// old
assert_eq!(format!("{}", ChannelId(1)), "<#1>");
assert_eq!(format!("{}", RoleId(2)), "<@&2>");
assert_eq!(format!("{}", UserId(3)), "<@3>");
// new
assert_eq!(format!("{}", ChannelId(1).mention()), "<#1>");
assert_eq!(format!("{}", RoleId(2)).mention()), "<@&2>");
assert_eq!(format!("{}", UserId(3).mention()), "<@3>");
When using EmbedBuilder::{image, thumbnail}, instead of calling another
builder, provide urls directly:
use serenity::model::Embed;
// old
Embed::fake(|e| e
.image(|i| i.url("https://not.zey.moe/me.png"))
.thumbnail(|t| t.url("https://not.zey.moe/me2.png")));
// new
Embed::fake(|e| e
.image("https://not.zey.moe/me.png")
.thumbnail("https://not.zey.moe/me2.png"));
When specifying a sharding method, instead of passing a u8 for sharding info,
pass a u64:
use serenity::Client;
let client = Client::login_bot(&env::var("DISCORD_TOKEN").unwrap());
// old
client.start_shard(1u8, 5u8); // or
client.start_shards(5u8); // or
client.start_shard_range([1u8, 3u8], 8u8);
// new
client.start_shard(1u64, 5u64); // or
client.start_shards(5u64); // or
client.start_shard_range([1u64, 3u64], 8u64);
Client.shards is now private. Instead of accessing it, don't.
When creating a Colour struct yourself, instead of specifying a single value
field, pass a single tuple value:
use serenity::utils::Colour;
// old
Colour {
value: 0,
}
// new
Colour(0);
Instead of using Attachment::download_to_directory to download an attachment
to a directory, do it yourself:
use std::fs::File;
use std::io::Write;
// assuming an `attachment` has already been bound
// old
attachment.download_to_directory("./attachments");
// new
let bytes = attachment.download().unwrap();
let filepath: PathBuf = path.as_ref().join(&attachment.filename);
let mut f = File::create(&filepath);
let _ = f.write(&bytes);
Instead of calling Message::is_webhook():
// assuming a `message` has already been bound
// old
let _ = message.is_webhook();
// new
let _ = message.webhook_id.is_some();
Instead of PartialGuild::find_role(role_id):
use serenity::model::RoleId;
// assuming a `guild` has already been bound
// old
let _ = guild.find_role(RoleId(1));
// new
let _ = guild.roles.get(RoleId(1));
Instead of Guild::{get_channel, get_member}, call:
use serenity::model::{ChannelId, UserId};
// assuming a `guild` has already been bound
// old
let _ = guild.get_channel(ChannelId(1));
let _ = guild.get_member(UserId(2));
// new
let _ = guild.channels.get(ChannelId(1));
let _ = guild.members.get(UserId(2));
Instead of using Context methods, use their Id or other struct equivalents.
voice feature no longer requires the cache feature to be enabled
[c:7b45f16]framework feature no longer requires the cache feature to be enabled
[c:86cd00f]Guild, InviteGuild, and PartialGuild now have splash_url methods
[c:d58c544]Message::webhook_id for messages sent via webhooks ([@fwrs])
[c:a2cbeb6]time::Tm to be passed into the embed timestamp field, in addition to
a direct string [c:b001234]Client::on_message() example ([@indiv0]) [c:bcb70e8]CurrentUser/User::static_avatar_url() methods to generate webp URLs
[c:c36841d]Colour struct ([@hsiW]) [c:2cb607d]4011 code (too many shards) ([@SunDwarf]) [c:93f3c60]Colour struct ([@bippum]) [c:345e140]User::default_avatar_url() [c:e85e901]Message::content_safe() to avoid @everyone/@heres ([@fwrs])
[c:e5a83dd]Member::distinct(), User::distinct() ([@fwrs]) [c:e5a83dd]User::avatar_url no longer mentions the user in the generated URL
[c:0708ccf]owners_only check now functions only if the author of a message
is an owner ([@fwrs]) [c:6355288]i64::MAX
seconds) [c:fafa363]before closure is now properly run when a message is sent by
the owner [c:760a47a]CurrentApplicationInfo now properly decodes due to flags no longer being
sent [c:2a743ce]Message::delete() permission check [c:4229034]command! macro signature as returning std::result::Result
[c:e9aae9c]User from rest::get_user -- not a CurrentUser [c:f57a187]Resumed event payload decoding [c:c2e8b69]CurrentApplicationInfo decoding without rpc_origins [c:38db32e]rest::execute_webhook be a POST [c:c050c59]format!("{}", UserId(7)) will format into "7" instead of "<@7>"
[c:933ee89]use_quotes for quote parsing to false (was true)
[c:38a484d]CreateEmbed builder now has direct image and thumbnail methods
instead of one-method builders [c:68c473d]u64 shard counts to allow using more than 255 shards (instead of
u8s) [c:ada07fa]Colour struct to be a tuplestruct [c:a8acd61]webhooks methods to get_webhooks
(eg: GuildChannel::webhooks() --> GuildChannel::get_webhooks())
[c:e8a9086]Guild::create_channel and related functions return a GuildChannel
[c:5918d01]Role's' Ord impl ([@emoticon]) [c:6a887b2]Shard::set_presence [c:5c40e85]serenity.rs to serenity ([@fwrs]) [c:3348178]Reaction::delete() [c:1594961]Arc/Message/RwLock clones [c:8c5ee70]This is a hotfix for applying a PR and fixing a major bug in the plain help command.
This is a hotfix for applying a PR and fixing a major bug in the plain help command.
Thanks to the following for contributions this release:
None.
Deprecate CreateEmbedImage::{height, width} and CreateEmbedThumbnail::{height, width}
This release focuses on revamping the framework, adding a large amount of configuration and overall features. v0.1.3 will be focused on performance optimizations and code cleanup.
Thanks to the following for contributions this release:
v0.1.2 can now be retrieved from the [crates.io listing].
When using EmbedBuilder::{image, thumbnail}, instead of calling another
builder, provide urls directly:
use serenity::model::Embed;
// old
Embed::fake(|e| e
.image(|i| i.url("https://not.zey.moe/me.png"))
.thumbnail(|t| t.url("https://not.zey.moe/me2.png")));
// new
Embed::fake(|e| e
.image("https://not.zey.moe/me.png")
.thumbnail("https://not.zey.moe/me2.png"));
From<Embed> for CreateEmbed [c:7914274]{Emoji,EmojiIdentifier}::url [c:ef6eba3]MessageBuilder ([@fwrs]) [c:13de5c2]CreateEmbedImage::{height, width} and
CreateEmbedThumbnail::{height, width}try!s have been converted to use ? syntax ([@acdenisSK])
[c:f69512b]v0.1.1 is a "features that v0.1.0 should have had" and "miscellaneous work" release. v0.1.2 will be focused on the framework, while v0.1.3 will be foc
v0.1.1 is a "features that v0.1.0 should have had" and "miscellaneous work" release. v0.1.2 will be focused on the framework, while v0.1.3 will be focused on performance optimizations.
Thanks to the following for contributions this release:
v0.1.1 can now be retrieved from the [crates.io listing].
When calling rest::get_guilds, instead of passing no parameters, pass a
GuildPagination variant and a limit:
use serenity::client::rest::{self, GuildPagination};
use serenity::model::GuildId;
// before
rest::get_guilds();
// after
rest::get_guilds(GuildPagination::After(GuildId(777)), 50);
Message::guild_id as a quick method for retrieving the Id of a message's
guild [c:bceb049]CurrentUser::guilds() to get the current user's guilds. Meant for use with
selfbots [c:57c060f]CurrentUser::edit() to edit the current user's profile settings [c:16d1b3c]User::distinct to format a string with the username#discriminator
combination ([@fwrs]) [c:31becb1]Member::colour to retrieve the member's colour ([@fwrs]) [c:43a5c5d]role1 < role2) for hierarchy [c:143337a]EditMember and EditProfile ([@Kiseii]) [c:e2557ac]Context.data's ShareMap. See
example 06 for an examplerest::start_integration_sync/Context::start_integration_sync now properly
work ([@abalabahaha]) [c:7f04179]Context::move_member's signature is now correct [c:4de39da]command! macro now publicly exports functions. This allows commands
created via this macro to be separated into different modules or crates
[c:62ed564]rest::get_guilds now supports pagination of guilds, as the output is now
limited to 100 [c:57c060f]Colour::dark_green is now sorted alphabetically ([@khazhyk]) [c:4a14b92]Colour::blitz_blue ([@Kiseii]) [c:daa24ec][0.12.5]: https://github.com/serenity-rs/serenity/compare/v0.12.4...v0.12.5 [0.12.4]: https://github.com/serenity-rs/serenity/compare/v0.12.3...v0.12.
Initial commit.
<!-- COMPARISONS -->
<!-- AUTHORS -->
<!-- COMMITS -->
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →