Skip to content

Releases: serenity-rs/serenity

v0.5.5

25 Jul 00:35
Compare
Choose a tag to compare

This release is mostly a bugfix release. Thanks to the following for their
contributions:

Added

Fixed

Changed

  • [model] Make Invite::guild and RichInvite::guild optional (@zeyla)
    c:3a647e3

Misc.

v0.5.4

07 Jun 22:10
Compare
Choose a tag to compare

Thanks to the following for their contributions:

v0.5.3

01 May 15:48
Compare
Choose a tag to compare

Thanks to the following for their contributions:

Added

Fixed

Misc.

v0.5.1

31 Jan 23:53
Compare
Choose a tag to compare

This release contains a number of fixes, a few more model helper methods, and
additional framework features.

Thanks to the following for their contributions:

Added

Fixed

Misc.

v0.4.8

31 Jan 23:54
Compare
Choose a tag to compare

This release contains a fix for managing panics in framework command dispatches.
A threadpool is now used, just like for event dispatches.

Fixed

  • [framework] Execute framework commands in a ThreadPool (@zeyla) c:5138193

v0.5.0

20 Jan 18:23
Compare
Choose a tag to compare

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:

Upgrade Path

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][0.5.0: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][0.5.0:example-09] 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][0.5.0:model] 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;

Added

  • [framework] Make the framework error's internal String public ([@acdenisSK])
    [c:3b9f0f8]
  • [client, gateway] Improve shard and shard runner logging ([@zeyla])
    [c:f0ee805]
  • [gateway] Have ConnectionStage derive Copy ([@acdenisSK]) [c:551f166]
  • [builder, framework, http, model] Replace Vec<T> parameter with more generic
    IntoIterator<Item=T> ([@ftriquet]) [c:b146501], [c:934eb3a]
  • [builder, gateway, model, voice] Make more parameters generic with trait
    bounds of AsRef ([@acdenisSK]) [c:e0e7617], [c:b62dfd4]
  • [framework, model] Add help command filtering, member prefix searching
    ([@Lakelezz]) [c:ee207b3]
  • [model] Add guild member filtering functions ([@Lakelezz]) [c:f26dad8]
  • [model] impl BanOptions for &str ([@acdenisSK]) [c:7c911d5]
  • [model] Derive Default on IDs and CurrentUser ([@acdenisSK]) [c:0881e18]
  • [client] Add a threadpool for event dispatches ([@zeyla]) [c:1fa83f7],
    [c:3e14067], [c:f2c21ef]
  • [model] Fall back to str::parse if parse_username fails ([@acdenisSK])
    [c:8c85664]
  • [model] Add a parsing fallback for RoleId ([@acdenisSK]) [c:5d4301b]
  • [http, model] Expand Audit Log support ([@acdenisSK]) [c:f491809]
  • [framework] Make Command::aliases public ([@acdenisSK]) [c:8c83866]
  • [model] impl FromStr for ReactionType ([@acdenisSK]) [c:2032a40],
    [c:84706f1]
  • [builder] Make trait bounds more generic, from Into<String> to Display
    ([@acdenisSK]) [c:05dad71]
  • [framework, internal, model, utils] Derive Debug on more public types
    ([@thelearnerofcode]) [c:e5a6f3a]
  • [model] Change PrivateChannel::say to accept a more generic argument
    ([@fenhl]) [c:a359f77]
  • [model] impl From<EmojiId, EmojiIdentifier> for ReactionType ([@fenhl])
    [c:68156c9]
  • [http] impl From<&Path> for AttachmentType ([@zeyla]) [c:7a5aa3c]
  • [model] Add GameType::Listening ([@hsiW], [@zeyla]) [c:40c5c12], [c:a17fea7]
  • [framework] Add cmd function to CreateCommand and CreateGroup
    ([@acdenisSK]) [c:e748d1f]
  • [model] Add Reaction::message function ([@Roughsketch]) [c:fd19446]
  • [model] Add Reaction::channel function ([@zeyla]) [c:e02a842]
  • [model] Add Reaction::user function ([@zeyla]) [c:82b87f1]
  • [model] Implement Deserialize for {,Gateway,Voice}Event ([@zeyla])
    [c:c3aa63f]
  • [framework] Add help() to CreateGroup ([@Lakelezz]) [c:39a1435]
  • [framework] Add a way to execute code when a command is registered
    ([@acdenisSK]) [c:f61816c]
  • [framework] Add before/after middleware to Command ([@acdenisSK])
    [c:4e20277]
  • [general] Switch from try_opt! macro to using ? operator ([@hsiW])
    [c:2d23d8b]
  • [framework] Make help commands customizable ([@Lakelezz]) [c:031fc92]
  • [model] Add VIEW_AUDIT_LOG permission ([@Lakelezz]) [c:612e973]
  • [model] Fallback to str::parse on ChannelId FromStr impl ([@acdenisSK])
    [c:0525ede]
  • [model] Add missing fields to Guild ([@zeyla]) [c:3d24033], [c:99d17d2],
    [c:2abeea5]
  • [framework] Add Args::len ([@acdenisSK]) [c:2c9b682], [c:b60d037],
    [c:143fddd]
  • [model] Add variant adapters to Channel ([@timotree3]) [c:f0a56f4]
  • [model] Add animated field to Emoji and ReactionType ([@zeyla])
    [c:f2fa349]
  • [framework] Better support for multiple delimiters on Args ([@Lakelezz])
    [c:62647f5]
  • [model] Update Region to include new voice regions ([@Flat]) [c:d264cc3]
  • [framework] Add Args::iter_quoted ([@acdenisSK]) [c:032c5a7]
  • [model] Add missing num implementations on models ([@zeyla]) [c:0b1f684]
  • [client] Add an event for shard connection changes ([@zeyla]) [c:7e46d8f]
  • [model] Implement or derive serde::Serialize on all models ([@zeyla])
    [c:25dddb6]
  • [model] Further generic-ify `reaction_us...
Read more

v0.4.3

01 Nov 20:41
Compare
Choose a tag to compare

This release contains bugfixes and marks the final release of the v0.4.x branch.
Future development will continue on the v0.5.x branch.

Thanks to the following for their contributions:

Added

Changed

  • [model] Rename Guild::permissions_for to Guild::permissions_in, keep an
    alias (@zeyla) c:dcac271

Fixed

  • [model] Make Member::permissions return guild-level permissions (@zeyla)
    c:d3eddc6

Misc.

v0.4.2

29 Oct 20:39
Compare
Choose a tag to compare

This release contains the regular bugfixes, new features and slight behaviour changes.

Thanks to the following people for their contributions:

Added

Fixed

Changed

Misc.

v0.4.1

14 Oct 20:16
Compare
Choose a tag to compare

This release contains bugfixes and some newly added or newly exposed
functionality.

Thanks to the following for their contributions this release:

Added

Fixed

Misc.

v0.4.0

25 Sep 17:09
Compare
Choose a tag to compare

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:

Upgrade Path

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::channel
  • Cache::get_guild --> Cache::guild
  • Cache::get_guild_channel --> Cache::guild_channel
  • Cache::get_member --> Cache::member
  • Cache::get_private_channel --> Cache::private_channel
  • Cache::get_role --> Cache::role
  • Cache::get_user --> Cache::user
  • ChannelId::get_invites --> ChannelId::invites
  • ChannelId::get_message --> ChannelId::message
  • ChannelId::get_messages --> ChannelId::messages
  • ChannelId::get_reaction_users --> ChannelId::get_reaction_users
  • ChannelId::get_webhooks --> ChannelId::webhooks
  • Channel::get_message --> Channel::message
  • Channel::get_messages --> Channel::messages
  • Channel::get_reaction_users --> Channel::reaction_users
  • Client::login_bot --> Client::new
  • Client::login --> Client::new
  • Colour::get_b --> Colour::b
  • Colour::get_g --> Colour::g
  • Colour::get_r --> Colour::r
  • Colour::get_tuple --> Colour::tuple
  • CurrentUser::distinct --> CurrentUser::tag
  • Group::get_message --> Group::message
  • Group::get_messages --> Group::messages
  • Group::get_reaction_users --> Group::reaction_users
  • Guild::get_bans --> Guild::bans
  • Guild::get_channels --> Guild::channels
  • Guild::get_emoji --> Guild::emoji
  • Guild::get_emojis --> Guild::emojis
  • Guild::get_integrations --> Guild::integrations
  • Guild::get_invites --> Guild::invites
  • Guild::get_member --> Guild::member
  • Guild::get_members --> Guild::members
  • Guild::get_member_named --> Guild::member_named
  • Guild::get_prune_count --> Guild::prune_count
  • Guild::get_webhooks --> Guild::webhooks
  • GuildId::get_bans --> GuildId::bans
  • GuildId::get_channels --> GuildId::channels
  • GuildId::get_emoji --> GuildId::emoji
  • GuildId::get_emojis --> GuildId::emojis
  • GuildId::get_integrations --> GuildId::integrations
  • GuildId::get_invites --> GuildId::invites
  • GuildId::get_member --> GuildId::member
  • GuildId::get_members --> GuildId::members
  • GuildId::get_prune_count --> GuildId::prune_count
  • GuildId::get_webhooks --> GuildId::webhooks
  • Message::get_reaction_users --> Message::reaction_users
  • PartialGuild::get_bans --> PartialGuild::bans
  • PartialGuild::get_channels --> PartialGuild::channels
  • PartialGuild::get_emoji --> PartialGuild::emoji
  • PartialGuild::get_emojis --> PartialGuild::emojis
  • PartialGuild::get_integrations --> PartialGuild::integrations
  • PartialGuild::get_invites --> PartialGuild::invites
  • PartialGuild::get_member --> PartialGuild::member
  • PartialGuild::get_members --> PartialGuild::members
  • PartialGuild::get_prune_count --> PartialGuild::prune_count
  • PartialGuild::get_webhooks --> PartialGuild::webhooks
  • PrivateChannel::get_message --> PrivateChannel::message
  • PrivateChannel::get_messages --> PrivateChannel::messages
  • PrivateChannel::get_reaction_users --> PrivateChannel::reaction_users
  • Role::edit_role --> Role::edit
  • User::distinct --> User::tag

http::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 s...
Read more