Skip to content

Commit

Permalink
Initial dirty attempt at crate split
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrasnitski committed Dec 8, 2024
1 parent f1b4e98 commit 9c5787c
Show file tree
Hide file tree
Showing 147 changed files with 437 additions and 1,094 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ rust-version = "1.82.0"
include = ["src/**/*", "LICENSE.md", "README.md", "CHANGELOG.md", "build.rs"]

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

[dependencies]
# Required dependencies
Expand Down Expand Up @@ -56,6 +56,7 @@ typesize = { version = "0.1.6", optional = true, features = ["url", "time", "ser
# serde feature only allows for serialisation,
# Serenity workspace crates
serenity-voice-model = { version = "0.2.0", path = "./voice-model", optional = true }
serenity-core = { path = "./serenity-core" }

[dev-dependencies.http_crate]
version = "1.1.0"
Expand Down Expand Up @@ -121,7 +122,7 @@ 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"]

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

# Enables compile-time heavy instrument macros from tracing
tracing_instrument = ["tracing/attributes"]
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
62 changes: 62 additions & 0 deletions serenity-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[package]
name = "serenity-core"
version = "0.1.0"
edition = "2021"

[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
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 }

[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"]
temp_cache = ["cache", "mini-moka", "typesize?/mini_moka"]
unstable = []
tracing_instrument = ["tracing/attributes"]
tokio_task_builder = ["tokio/tracing"]
voice_model = ["serenity-voice-model"]

rustls_backend = [
"reqwest/rustls-tls",
"tokio-tungstenite/rustls-tls-webpki-roots",
]

native_tls_backend = [
"reqwest/native-tls",
"tokio-tungstenite/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.
15 changes: 15 additions & 0 deletions serenity-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[macro_use]
extern crate serde;

#[macro_use]
mod internal;

mod constants;
pub mod secrets;

pub mod builder;
pub mod cache;
pub mod error;
pub mod http;
pub mod model;
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.
56 changes: 0 additions & 56 deletions src/model/event.rs → serenity-core/src/model/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@
#![allow(clippy::option_option)]

use nonmax::NonMaxU64;
use serde::de::Error as DeError;
use serde::Serialize;
use strum::{EnumCount, IntoStaticStr, VariantNames};

use crate::constants::Opcode;
use crate::internal::utils::lending_for_each;
use crate::model::prelude::*;
use crate::model::utils::remove_from_map;

/// Requires no gateway intents.
///
Expand Down Expand Up @@ -1065,59 +1062,6 @@ pub struct MessagePollVoteRemoveEvent {
pub answer_id: AnswerId,
}

/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#payload-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Debug, Clone, Serialize)]
#[non_exhaustive]
#[serde(untagged)]
pub enum GatewayEvent {
Dispatch {
seq: u64,
// Avoid deserialising straight away to handle errors and get access to `seq`.
data: JsonMap,
// Used for debugging, if the data cannot be deserialised.
original_str: FixedString,
},
Heartbeat(u64),
Reconnect,
/// Whether the session can be resumed.
InvalidateSession(bool),
Hello(u64),
HeartbeatAck,
}

// Manual impl needed to emulate integer enum tags
impl<'de> Deserialize<'de> for GatewayEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let mut map = JsonMap::deserialize(deserializer)?;

Ok(match remove_from_map(&mut map, "op")? {
Opcode::Dispatch => {
Self::Dispatch {
seq: remove_from_map(&mut map, "s")?,
// Filled in in recv_event
original_str: FixedString::new(),
data: map,
}
},
Opcode::Heartbeat => Self::Heartbeat(remove_from_map(&mut map, "s")?),
Opcode::InvalidSession => Self::InvalidateSession(remove_from_map(&mut map, "d")?),
Opcode::Hello => {
#[derive(Deserialize)]
struct HelloPayload {
heartbeat_interval: u64,
}

let inner: HelloPayload = remove_from_map(&mut map, "d")?;
Self::Hello(inner.heartbeat_interval)
},
Opcode::Reconnect => Self::Reconnect,
Opcode::HeartbeatAck => Self::HeartbeatAck,
_ => return Err(DeError::custom("invalid opcode")),
})
}
}

/// Event received over a websocket connection
///
/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#receive-events).
Expand Down
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.
4 changes: 0 additions & 4 deletions src/utils/mod.rs → serenity-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! A set of utilities to help with common use cases that are not required to fully use the
//! library.
#[cfg(feature = "gateway")]
mod argument_convert;
#[cfg(feature = "cache")]
mod content_safe;
mod custom_message;
Expand All @@ -11,8 +9,6 @@ mod message_builder;

use std::num::NonZeroU16;

#[cfg(feature = "gateway")]
pub use argument_convert::*;
#[cfg(feature = "cache")]
pub use content_safe::*;
pub use formatted_timestamp::*;
Expand Down
8 changes: 4 additions & 4 deletions src/collector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ make_specific_collector!(
CollectComponentInteractions, collect_component_interactions,
// This defines the extractor pattern, which extracts the data we want to collect from an Event.
Event::InteractionCreate(InteractionCreateEvent {
interaction: Interaction::Component(interaction),
interaction: Interaction::Component(interaction), ..
}) => interaction,
// All following lines define built-in filters of the collector.
// Each line consists of:
Expand All @@ -186,7 +186,7 @@ make_specific_collector!(
ModalInteractionCollector, ModalInteraction,
CollectModalInteractions, collect_modal_interactions,
Event::InteractionCreate(InteractionCreateEvent {
interaction: Interaction::Modal(interaction),
interaction: Interaction::Modal(interaction), ..
}) => interaction,
author_id: UserId => interaction.user.id == *author_id,
channel_id: ChannelId => interaction.channel_id == *channel_id,
Expand All @@ -197,7 +197,7 @@ make_specific_collector!(
make_specific_collector!(
ReactionCollector, Reaction,
CollectReactions, collect_reactions,
Event::ReactionAdd(ReactionAddEvent { reaction }) => reaction,
Event::ReactionAdd(ReactionAddEvent { reaction, .. }) => reaction,
author_id: UserId => reaction.user_id.is_none_or(|a| a == *author_id),
channel_id: ChannelId => reaction.channel_id == *channel_id,
guild_id: GuildId => reaction.guild_id.is_none_or(|g| g == *guild_id),
Expand All @@ -206,7 +206,7 @@ make_specific_collector!(
make_specific_collector!(
MessageCollector, Message,
CollectMessages, collect_messages,
Event::MessageCreate(MessageCreateEvent { message }) => message,
Event::MessageCreate(MessageCreateEvent { message, .. }) => message,
author_id: UserId => message.author.id == *author_id,
channel_id: ChannelId => message.channel_id == *channel_id,
guild_id: GuildId => message.guild_id.is_none_or(|g| g == *guild_id),
Expand Down
Loading

0 comments on commit 9c5787c

Please sign in to comment.