1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
mod member;
pub use member::*;
mod message;
pub use message::*;
mod user;
pub use user::*;
mod channel;
pub use channel::*;
// From HTTP you can only get PartialGuild; for Guild you need gateway and cache
#[cfg(feature = "cache")]
mod guild;
#[cfg(feature = "cache")]
pub use guild::*;
mod role;
pub use role::*;
mod emoji;
pub use emoji::*;
use super::DOMAINS;
use crate::model::prelude::*;
use crate::prelude::*;
/// Parse a value from a string in context of a received message.
///
/// This trait is a superset of [`std::str::FromStr`]. The difference is that this trait aims to
/// support serenity-specific Discord types like [`Member`] or [`Message`].
///
/// Trait implementations may do network requests as part of their parsing procedure.
///
/// Useful for implementing argument parsing in command frameworks.
#[async_trait::async_trait]
pub trait ArgumentConvert: Sized {
/// The associated error which can be returned from parsing.
type Err;
/// Parses a string `s` as a command parameter of this type.
async fn convert(
ctx: impl CacheHttp,
guild_id: Option<GuildId>,
channel_id: Option<ChannelId>,
s: &str,
) -> Result<Self, Self::Err>;
}
#[async_trait::async_trait]
impl<T: std::str::FromStr> ArgumentConvert for T {
type Err = <T as std::str::FromStr>::Err;
async fn convert(
_: impl CacheHttp,
_: Option<GuildId>,
_: Option<ChannelId>,
s: &str,
) -> Result<Self, Self::Err> {
T::from_str(s)
}
}
// The following few parse_XXX methods are in here (parse.rs) because they need to be gated behind
// the model feature and it's just convenient to put them here for that
/// Retrieves IDs from "{channel ID}-{message ID}" (retrieved by shift-clicking on "Copy ID").
///
/// If the string is invalid, None is returned.
///
/// # Examples
/// ```rust
/// use serenity::model::prelude::*;
/// use serenity::utils::parse_message_id_pair;
///
/// assert_eq!(
/// parse_message_id_pair("673965002805477386-842482646604972082"),
/// Some((ChannelId::new(673965002805477386), MessageId::new(842482646604972082))),
/// );
/// assert_eq!(
/// parse_message_id_pair("673965002805477386-842482646604972082-472029906943868929"),
/// None,
/// );
/// ```
#[must_use]
pub fn parse_message_id_pair(s: &str) -> Option<(ChannelId, MessageId)> {
let mut parts = s.splitn(2, '-');
let channel_id = parts.next()?.parse().ok()?;
let message_id = parts.next()?.parse().ok()?;
Some((channel_id, message_id))
}
/// Retrieves guild, channel, and message ID from a message URL.
///
/// If the URL is malformed, None is returned.
///
/// # Examples
/// ```rust
/// use serenity::model::prelude::*;
/// use serenity::utils::parse_message_url;
///
/// assert_eq!(
/// parse_message_url(
/// "https://discord.com/channels/381880193251409931/381880193700069377/806164913558781963"
/// ),
/// Some((
/// GuildId::new(381880193251409931),
/// ChannelId::new(381880193700069377),
/// MessageId::new(806164913558781963),
/// )),
/// );
/// assert_eq!(
/// parse_message_url(
/// "https://canary.discord.com/channels/381880193251409931/381880193700069377/806164913558781963"
/// ),
/// Some((
/// GuildId::new(381880193251409931),
/// ChannelId::new(381880193700069377),
/// MessageId::new(806164913558781963),
/// )),
/// );
/// assert_eq!(parse_message_url("https://google.com"), None);
/// ```
#[must_use]
pub fn parse_message_url(s: &str) -> Option<(GuildId, ChannelId, MessageId)> {
for domain in DOMAINS {
if let Some(parts) = s.strip_prefix(&format!("https://{domain}/channels/")) {
let mut parts = parts.splitn(3, '/');
let guild_id = parts.next()?.parse().ok()?;
let channel_id = parts.next()?.parse().ok()?;
let message_id = parts.next()?.parse().ok()?;
return Some((guild_id, channel_id, message_id));
}
}
None
}