Skip to content

Commit

Permalink
Split out core functionality into serenity-core crate
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrasnitski committed Jan 30, 2025
1 parent 358336e commit 0aa231d
Show file tree
Hide file tree
Showing 147 changed files with 469 additions and 1,106 deletions.
53 changes: 17 additions & 36 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ edition.workspace = true
rust-version.workspace = true

[workspace]
members = ["examples/*"]
members = ["examples/*", "serenity-core"]

[workspace.package]
documentation = "https://docs.rs/serenity"
Expand All @@ -28,48 +28,30 @@ rust-version = "1.82"

[dependencies]
# Required dependencies
bitflags = "2.4.2"
serde_json = "1.0.108"
async-trait = "0.1.74"
tracing = { version = "0.1.40", features = ["log"] }
serde = { version = "1.0.192", features = ["derive", "rc"] }
url = { version = "2.4.1", features = ["serde"] }
tokio = { version = "1.34.0", features = ["macros", "rt", "sync", "time", "io-util"] }
futures = { version = "0.3.29", default-features = false, features = ["std"] }
dep_time = { version = "0.3.36", package = "time", features = ["formatting", "parsing", "serde-well-known"] }
base64 = { version = "0.22.0" }
zeroize = { version = "1.7" } # Not used in serenity, but bumps the minimal version from secrecy
arrayvec = { version = "0.7.4", features = ["serde"] }
serde_cow = { version = "0.1.0" }
small-fixed-array = { version = "0.4", features = ["serde"] }
bool_to_bitflags = { version = "0.1.2" }
nonmax = { version = "0.5.5", features = ["serde"] }
strum = { version = "0.26", features = ["derive"] }
to-arraystring = "0.2.0"
extract_map = { version = "0.1.0", features = ["serde", "iter_mut"] }
aformat = "0.1.3"
bytes = "1.5.0"
# Optional dependencies
fxhash = { version = "0.2.1", optional = true }
chrono = { version = "0.4.31", default-features = false, features = ["clock", "serde"], optional = true }
flate2 = { version = "1.0.28", optional = true }
zstd-safe = { version = "7.2.1", optional = true }
reqwest = { version = "0.12.2", default-features = false, features = ["multipart", "stream", "json"], optional = true }
tokio-tungstenite = { version = "0.24.0", features = ["url"], optional = true }
percent-encoding = { version = "2.3.0", optional = true }
mini-moka = { version = "0.10.2", optional = true }
mime_guess = { version = "2.0.4", optional = true }
dashmap = { version = "6.1.0", features = ["serde"], optional = true }
parking_lot = { version = "0.12.1"}
ed25519-dalek = { version = "2.0.0", optional = true }
typesize = { version = "0.1.6", optional = true, features = ["url", "time", "serde_json", "secrecy", "parking_lot", "nonmax", "extract_map_01"] }
# serde feature only allows for serialisation,
# Serenity workspace crates
serenity-voice-model = { version = "0.2.0", path = "./voice-model", optional = true }

[dev-dependencies.http_crate]
version = "1.1.0"
package = "http"
serenity-core = { path = "./serenity-core" }

[features]
# Defaults with different backends
Expand All @@ -87,40 +69,40 @@ default_no_backend = [

# Enables builder structs to configure Discord HTTP requests. Without this feature, you have to
# construct JSON manually at some places.
builder = ["tokio/fs"]
builder = ["serenity-core/builder"]
# Enables the cache, which stores the data received from Discord gateway to provide access to
# complete guild data, channels, users and more without needing HTTP requests.
cache = ["fxhash", "dashmap"]
cache = ["serenity-core/cache"]
# Enables collectors, a utility feature that lets you await interaction events in code with
# zero setup, without needing to setup an InteractionCreate event listener.
collector = ["gateway"]
# Enables the Framework trait which is an abstraction for old-style text commands.
framework = ["gateway"]
# Enables gateway support, which allows bots to listen for Discord events.
gateway = ["model", "flate2"]
gateway = ["model", "flate2", "reqwest"]
# Enables HTTP, which enables bots to execute actions on Discord.
http = ["dashmap", "mime_guess", "percent-encoding"]
http = ["serenity-core/http"]
# Enables wrapper methods around HTTP requests on model types.
# Requires "builder" to configure the requests and "http" to execute them.
# Note: the model type definitions themselves are always active, regardless of this feature.
# TODO: remove dependeny on utils feature
model = ["builder", "http", "utils"]
voice_model = ["serenity-voice-model"]
model = ["serenity-core/model", "builder", "http", "utils"]
voice_model = ["serenity-core/voice_model"]
# Enables zlib-stream transport compression of incoming gateway events.
transport_compression_zlib = ["flate2", "gateway"]
# Enables zstd-stream transport compression of incoming gateway events.
transport_compression_zstd = ["zstd-safe", "gateway"]
# Enables support for Discord API functionality that's not stable yet, as well as serenity APIs that
# are allowed to change even in semver non-breaking updates.
unstable = []
unstable = ["serenity-core/unstable"]
# Enables some utility functions that can be useful for bot creators.
utils = []
utils = ["serenity-core/utils"]
voice = ["gateway"]
# Enables unstable tokio features to give explicit names to internally spawned tokio tasks
tokio_task_builder = ["tokio/tracing"]
tokio_task_builder = ["tokio/tracing", "serenity-core/tokio_task_builder"]
interactions_endpoint = ["ed25519-dalek"]
# Uses chrono for Timestamp, instead of time
chrono = ["dep:chrono", "typesize?/chrono"]
chrono = ["serenity-core/chrono"]

# This enables all parts of the serenity codebase
# (Note: all feature-gated APIs to be documented should have their features listed here!)
Expand All @@ -129,27 +111,26 @@ chrono = ["dep:chrono", "typesize?/chrono"]
full = ["default", "collector", "voice", "voice_model", "interactions_endpoint"]

# Enables temporary caching in functions that retrieve data via the HTTP API.
temp_cache = ["cache", "mini-moka", "typesize?/mini_moka"]
temp_cache = ["serenity-core/temp_cache"]

typesize = ["dep:typesize", "dashmap/typesize", "small-fixed-array/typesize", "bool_to_bitflags/typesize"]
typesize = ["dep:typesize", "serenity-core/typesize"]

# Enables compile-time heavy instrument macros from tracing
tracing_instrument = ["tracing/attributes"]
tracing_instrument = ["serenity-core/tracing_instrument", "tracing/attributes"]

# Backends to pick from:
# - Rustls Backends
rustls_backend = [
"reqwest/rustls-tls",
"serenity-core/rustls_backend",
"tokio-tungstenite/rustls-tls-webpki-roots",
]

# - Native TLS Backends
native_tls_backend = [
"reqwest/native-tls",
"serenity-core/native_tls_backend",
"tokio-tungstenite/native-tls",
]


[package.metadata.docs.rs]
features = ["full"]
rustdoc-args = ["--cfg", "docsrs"]
Expand Down
1 change: 1 addition & 0 deletions examples/testing/src/model_type_sizes.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serenity::gateway::GatewayEvent;
use serenity::model::prelude::*;

pub fn print_ranking() {
Expand Down
71 changes: 71 additions & 0 deletions serenity-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[package]
name = "serenity-core"
version = "0.12.4"

documentation.workspace = true
homepage.workspace = true
repository.workspace = true
keywords.workspace = true
license.workspace = true
edition.workspace = true
rust-version.workspace = true


[dependencies]
bitflags = "2.4.2"
base64 = { version = "0.22.0" }
serde_json = "1.0.108"
serde = { version = "1.0.192", features = ["derive", "rc"] }
nonmax = { version = "0.5.5", features = ["serde"] }
to-arraystring = "0.2.0"
tokio = { version = "1.34.0", features = ["macros", "rt", "sync", "time", "io-util"] }
zeroize = { version = "1.7" } # Not used in serenity, but bumps the minimal version from secrecy
time = { version = "0.3.36", features = ["formatting", "parsing", "serde-well-known"] }
strum = { version = "0.26", features = ["derive"] }
fxhash = { version = "0.2.1", optional = true }
chrono = { version = "0.4.31", default-features = false, features = ["clock", "serde"], optional = true }
dashmap = { version = "6.1.0", features = ["serde"], optional = true }
mime_guess = { version = "2.0.4", optional = true }
percent-encoding = { version = "2.3.0", optional = true }
small-fixed-array = { version = "0.4", features = ["serde"] }
bool_to_bitflags = { version = "0.1.2" }
futures = { version = "0.3.29", default-features = false, features = ["std"] }
reqwest = { version = "0.12.2", default-features = false, features = ["multipart", "stream", "json"], optional = true }
tokio-tungstenite = { version = "0.21.0", optional = true }
typesize = { version = "0.1.6", optional = true, features = ["url", "time", "serde_json", "secrecy", "parking_lot", "nonmax", "extract_map_01"] }
extract_map = { version = "0.1.0", features = ["serde", "iter_mut"] }
serde_cow = { version = "0.1.0" }
aformat = "0.1.3"
arrayvec = { version = "0.7.4", features = ["serde"] }
url = { version = "2.4.1", features = ["serde"] }
bytes = "1.5.0"
parking_lot = { version = "0.12.1"}
mini-moka = { version = "0.10.2", optional = true }
tracing = { version = "0.1.40", features = ["log"] }
serenity-voice-model = { version = "0.2.0", path = "../voice-model", optional = true }

[dev-dependencies.http_crate]
version = "1.1.0"
package = "http"

[features]
default = ["cache", "chrono", "model", "rustls_backend"]

builder = ["tokio/fs"]
cache = ["fxhash", "dashmap"]
http = ["dashmap", "mime_guess", "percent-encoding"]
model = ["builder", "http", "utils"]
utils = []
chrono = ["dep:chrono", "typesize?/chrono"]
typesize = ["dep:typesize", "dashmap/typesize", "small-fixed-array/typesize", "bool_to_bitflags/typesize"]

unstable = []
tracing_instrument = ["tracing/attributes"]
tokio_task_builder = ["tokio/tracing"]
voice_model = ["serenity-voice-model"]

temp_cache = ["cache", "mini-moka", "typesize?/mini_moka"]

rustls_backend = ["reqwest/rustls-tls"]

native_tls_backend = ["reqwest/native-tls"]
13 changes: 13 additions & 0 deletions serenity-core/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[cfg(all(feature = "http", not(any(feature = "rustls_backend", feature = "native_tls_backend"))))]
compile_error!(
"You have the `http` feature enabled; either the `rustls_backend` or `native_tls_backend` \
feature must be enabled to let Serenity make requests over the network.\n\
- `rustls_backend` uses Rustls, a pure Rust TLS-implemenation.\n\
- `native_tls_backend` uses SChannel on Windows, Secure Transport on macOS, and OpenSSL on \
other platforms.\n\
If you are unsure, go with `rustls_backend`."
);

fn main() {
println!("cargo:rustc-check-cfg=cfg(tokio_unstable, ignore_serenity_deprecated)");
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
30 changes: 30 additions & 0 deletions serenity-core/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! A set of constants used by the library.
use nonmax::NonMaxU16;

/// The maximum length of the textual size of an embed.
pub const EMBED_MAX_LENGTH: usize = 6000;

/// The maximum number of embeds in a message.
pub const EMBED_MAX_COUNT: usize = 10;

/// The maximum number of stickers in a message.
pub const STICKER_MAX_COUNT: usize = 3;

/// The maximum unicode code points allowed within a message by Discord.
pub const MESSAGE_CODE_LIMIT: usize = 2000;

/// The maximum number of members the bot can fetch at once
pub const MEMBER_FETCH_LIMIT: NonMaxU16 = match NonMaxU16::new(1000) {
Some(m) => m,
None => unreachable!(),
};

/// The [UserAgent] sent along with every request.
///
/// [UserAgent]: ::reqwest::header::USER_AGENT
pub const USER_AGENT: &str = concat!(
"DiscordBot (https://github.com/serenity-rs/serenity, ",
env!("CARGO_PKG_VERSION"),
")"
);
114 changes: 114 additions & 0 deletions serenity-core/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;

#[cfg(feature = "http")]
use reqwest::{header::InvalidHeaderValue, Error as ReqwestError};

#[cfg(feature = "http")]
use crate::http::HttpError;
use crate::internal::prelude::*;
use crate::model::ModelError;
use crate::secrets::TokenError;

/// The common result type between most library functions.
///
/// The library exposes functions which, for a result type, exposes only one type, rather than the
/// usual 2 (`Result<T, Error>`). This is because all functions that return a result return
/// serenity's [`Error`], so this is implied, and a "simpler" result is used.
pub type Result<T, E = Error> = StdResult<T, E>;

/// A common error enum returned by most of the library's functionality within a custom [`Result`].
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
/// An [`std::io`] error.
Io(IoError),
/// An error from the [`serde_json`] crate.
Json(serde_json::Error),
/// An error from the [`model`] module.
///
/// [`model`]: crate::model
Model(ModelError),
/// An error from the [`http`] module.
///
/// [`http`]: crate::http
#[cfg(feature = "http")]
Http(HttpError),
/// An error from the [`secrets`] module.
///
/// [`secrets`]: crate::secrets
Token(TokenError),
}

impl From<IoError> for Error {
fn from(e: IoError) -> Error {
Error::Io(e)
}
}

impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error::Json(e)
}
}

impl From<ModelError> for Error {
fn from(e: ModelError) -> Error {
Error::Model(e)
}
}

#[cfg(feature = "http")]
impl From<HttpError> for Error {
fn from(e: HttpError) -> Error {
Error::Http(e)
}
}

impl From<TokenError> for Error {
fn from(e: TokenError) -> Error {
Error::Token(e)
}
}

#[cfg(feature = "http")]
impl From<InvalidHeaderValue> for Error {
fn from(e: InvalidHeaderValue) -> Error {
HttpError::InvalidHeader(e).into()
}
}

#[cfg(feature = "http")]
impl From<ReqwestError> for Error {
fn from(e: ReqwestError) -> Error {
HttpError::Request(e).into()
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Io(inner) => fmt::Display::fmt(&inner, f),
Self::Json(inner) => fmt::Display::fmt(&inner, f),
Self::Model(inner) => fmt::Display::fmt(&inner, f),
#[cfg(feature = "http")]
Self::Http(inner) => fmt::Display::fmt(&inner, f),
Self::Token(inner) => fmt::Display::fmt(&inner, f),
}
}
}

impl StdError for Error {
#[cfg_attr(feature = "tracing_instrument", instrument)]
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Self::Io(inner) => Some(inner),
Self::Json(inner) => Some(inner),
Self::Model(inner) => Some(inner),
#[cfg(feature = "http")]
Self::Http(inner) => Some(inner),
Self::Token(inner) => Some(inner),
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
19 changes: 19 additions & 0 deletions serenity-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[macro_use]
extern crate serde;

#[macro_use]
mod internal;

mod constants;
pub mod secrets;

#[cfg(feature = "builder")]
pub mod builder;
#[cfg(feature = "cache")]
pub mod cache;
pub mod error;
#[cfg(feature = "http")]
pub mod http;
pub mod model;
#[cfg(feature = "utils")]
pub mod utils;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 0aa231d

Please sign in to comment.