fn reaction_add(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
    let emoji_string = args.single::<String>()?;
    let emoji_str: &str = emoji_string.as_ref();
    let emoji = {
        match serenity::utils::parse_emoji(emoji_str) {
            Some(emoji) => Some(emoji),
            None => {
                if emoji_str.starts_with("<a:") {
                    let mut split = emoji_str.split(':');
                    let name = split.nth(1).ok_or("Failed to parse emoji")?;
                    log::debug!("emoji name: {}", name);
                    let id = split
                        .next()
                        .ok_or("Failed to get name of emoji")?
                        .trim_end_matches('>');
                    log::debug!("emoji id: {}", id);
                    Some(serenity::model::misc::EmojiIdentifier {
                        id: serenity::model::id::EmojiId(id.parse::<u64>()?),
                        name: name.to_string(),
                    })
                } else if !emoji_str.is_ascii() {
                    None
                } else {
                    return Err(CommandError("Error parsing emoji".to_string()));
                }
            }
        }
    };
    let role_id = {
        match args.single::<RoleId>() {
            Ok(role_id) => role_id,
            Err(_) => RoleId(
                serenity::utils::parse_role(args.single::<String>()?)
                    .ok_or("Couldn't parse role id")?,
            ),
        }
    };

    let message = args.single::<String>()?;
    // The lazy_static will only panic if the regex itself is invalid, and therefore, shouldn't
    // ever panic.
    // regex test link: https://regex101.com/r/Rth5jE/6
    // rust playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7bc300a4af839a35ec3a9c4daf9344da
    lazy_static! {
        static ref REGEX: Regex = Regex::new(
            r"(?m)http[s]?://?(?:ptb\.|canary\.)?discord(?:app)?\.com/channels/\d*/(\d*)/(\d*)",
        )
        .expect("Invalid regex, this should never happen.");
    }
    let capture = REGEX.captures(&message).ok_or("Couldn't find message id")?;
    let message_id = {
        let id = capture
            .get(2)
            .ok_or("Couldn't get messsage id")?
            .as_str()
            .parse::<u64>()?;

        MessageId(id)
    };
    let guild_id = msg.guild_id.ok_or("Couldn't get guild id")?;

    let (fancy_db, runtime_lock) = {
        let data = ctx.data.read();
        let fancy_db = Arc::clone(data.get::<PoolContainer>().ok_or("Couldn't get fancy db")?);
        let runtime_lock = Arc::clone(
            data.get::<TokioContainer>()
                .ok_or("Couldn't get runtime lock")?,
        );
        (fancy_db, runtime_lock)
    };

    {
        let mut tokio = runtime_lock.try_lock()?;
        if let Some(emoji_indentifier) = emoji {
            log::debug!(
                "Custom Emoji: {}:{}",
                emoji_indentifier.name,
                emoji_indentifier.id
            );
            tokio.block_on(
                sqlx::query!("INSERT INTO reaction_roles (guild_id, role_id, message_id, emoji_id, name) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (role_id) DO UPDATE SET guild_id = $1, role_id = $2, message_id = $3, emoji_id = $4, name = $5",
                        guild_id.0 as i64,
                        role_id.0 as i64,
                        message_id.0 as i64,
                        emoji_indentifier.id.0 as i64,
                        emoji_indentifier.name
                    ).execute(fancy_db.pool())
            )?;
            ctx.http.create_reaction(
                capture
                    .get(1)
                    .ok_or("Failed to get channel_id to add reaction to the linked message")?
                    .as_str()
                    .parse::<u64>()?,
                message_id.0,
                &emoji_indentifier.into(),
            )?;
        } else {
            log::debug!("Unicode emoji: {}", emoji_str);
            tokio.block_on(sqlx::query!("INSERT INTO reaction_roles (guild_id, role_id, message_id, name) VALUES ($1, $2, $3, $4) ON CONFLICT (role_id) DO UPDATE SET guild_id = $1, role_id = $2, message_id = $3, name = $4",
                        guild_id.0 as i64,
                        role_id.0 as i64,
                        message_id.0 as i64,
                        emoji_str
                    ).execute(fancy_db.pool())
            )?;
            ctx.http.create_reaction(
                capture
                    .get(1)
                    .ok_or("Failed to get channel_id to add reaction to the linked message")?
                    .as_str()
                    .parse::<u64>()?,
                message_id.0,
                &emoji_str.into(),
            )?;
        }
    }

    // Attempt to find role in cache,
    // if found, return the name of the role,
    // if not found, return a mention of the role.
    let role_name_or_id = {
        match role_id.to_role_cached(&ctx) {
            Some(role) => role.name,
            None => format!("<@&{}>", role_id.0),
        }
    };

    msg
        .channel_id
        .say(&ctx.http, format!("Successfully added the role `{}`, with the emoji {}, to the message:\nhttps://discordapp.com/channels/{}/{}/{}", role_name_or_id, emoji_str, guild_id.0, msg.channel_id.0, message_id))
        .map_or_else(|e| Err(CommandError(e.to_string())), |_| Ok(()))
}
/// Allows you to add a reaction to a message, that a user
/// can click on to give them the role you specified.
/// If you already added a role, this command will update
/// to the role to use either the new emoji or on a different message.
///
/// Example usage:
/// a.reaction_add <emoji> <role_id> <message_url>
/// a.reaction_add :blue_heart: 401927402072309760 https://discordapp.com/channels/197169999494774784/355889026726887426/703682563398697000
///
/// Restricted to Users with the Administrator permission
Allows you to add a reaction to a message, that a user
can click on to give them the role you specified.
If you already added a role, this command will update
to the role to use either the new emoji or on a different message.



Restricted to Users with the Administrator permission
Allows you to add a reaction to a message that a user can click on to give them the role you specified . If you already added a role this command will update to the role to use either the new emoji or on a different message . Restricted to Users with the Administrator permission
fn reaction_add(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
    let emoji_string = args.single::<String>()?;
    let emoji_str: &str = emoji_string.as_ref();
    let emoji = {
        match serenity::utils::parse_emoji(emoji_str) {
            Some(emoji) => Some(emoji),
            None => {
                if emoji_str.starts_with("<a:") {
                    let mut split = emoji_str.split(':');
                    let name = split.nth(1).ok_or("Failed to parse emoji")?;
                    log::debug!("emoji name: {}", name);
                    let id = split
                        .next()
                        .ok_or("Failed to get name of emoji")?
                        .trim_end_matches('>');
                    log::debug!("emoji id: {}", id);
                    Some(serenity::model::misc::EmojiIdentifier {
                        id: serenity::model::id::EmojiId(id.parse::<u64>()?),
                        name: name.to_string(),
                    })
                } else if !emoji_str.is_ascii() {
                    None
                } else {
                    return Err(CommandError("Error parsing emoji".to_string()));
                }
            }
        }
    };
    let role_id = {
        match args.single::<RoleId>() {
            Ok(role_id) => role_id,
            Err(_) => RoleId(
                serenity::utils::parse_role(args.single::<String>()?)
                    .ok_or("Couldn't parse role id")?,
            ),
        }
    };
    let message = args.single::<String>()?;
    // The lazy_static will only panic if the regex itself is invalid, and therefore, shouldn't
    // ever panic.
    // regex test link: https://regex101.com/r/Rth5jE/6
    // rust playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7bc300a4af839a35ec3a9c4daf9344da
    lazy_static! {
        static ref REGEX: Regex = Regex::new(
            r"(?m)http[s]?://?(?:ptb\.|canary\.)?discord(?:app)?\.com/channels/\d*/(\d*)/(\d*)",
        )
        .expect("Invalid regex, this should never happen.");
    }
    let capture = REGEX.captures(&message).ok_or("Couldn't find message id")?;
    let message_id = {
        let id = capture
            .get(2)
            .ok_or("Couldn't get messsage id")?
            .as_str()
            .parse::<u64>()?;
        MessageId(id)
    };
    let guild_id = msg.guild_id.ok_or("Couldn't get guild id")?;
    let (fancy_db, runtime_lock) = {
        let data = ctx.data.read();
        let fancy_db = Arc::clone(data.get::<PoolContainer>().ok_or("Couldn't get fancy db")?);
        let runtime_lock = Arc::clone(
            data.get::<TokioContainer>()
                .ok_or("Couldn't get runtime lock")?,
        );
        (fancy_db, runtime_lock)
    };
    {
        let mut tokio = runtime_lock.try_lock()?;
        if let Some(emoji_indentifier) = emoji {
            log::debug!(
                "Custom Emoji: {}:{}",
                emoji_indentifier.name,
                emoji_indentifier.id
            );
            tokio.block_on(
                sqlx::query!("INSERT INTO reaction_roles (guild_id, role_id, message_id, emoji_id, name) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (role_id) DO UPDATE SET guild_id = $1, role_id = $2, message_id = $3, emoji_id = $4, name = $5",
                        guild_id.0 as i64,
                        role_id.0 as i64,
                        message_id.0 as i64,
                        emoji_indentifier.id.0 as i64,
                        emoji_indentifier.name
                    ).execute(fancy_db.pool())
            )?;
            ctx.http.create_reaction(
                capture
                    .get(1)
                    .ok_or("Failed to get channel_id to add reaction to the linked message")?
                    .as_str()
                    .parse::<u64>()?,
                message_id.0,
                &emoji_indentifier.into(),
            )?;
        } else {
            log::debug!("Unicode emoji: {}", emoji_str);
            tokio.block_on(sqlx::query!("INSERT INTO reaction_roles (guild_id, role_id, message_id, name) VALUES ($1, $2, $3, $4) ON CONFLICT (role_id) DO UPDATE SET guild_id = $1, role_id = $2, message_id = $3, name = $4",
                        guild_id.0 as i64,
                        role_id.0 as i64,
                        message_id.0 as i64,
                        emoji_str
                    ).execute(fancy_db.pool())
            )?;
            ctx.http.create_reaction(
                capture
                    .get(1)
                    .ok_or("Failed to get channel_id to add reaction to the linked message")?
                    .as_str()
                    .parse::<u64>()?,
                message_id.0,
                &emoji_str.into(),
            )?;
        }
    }
    // Attempt to find role in cache,
    // if found, return the name of the role,
    // if not found, return a mention of the role.
    let role_name_or_id = {
        match role_id.to_role_cached(&ctx) {
            Some(role) => role.name,
            None => format!("<@&{}>", role_id.0),
        }
    };
    msg
        .channel_id
        .say(&ctx.http, format!("Successfully added the role `{}`, with the emoji {}, to the message:\nhttps://discordapp.com/channels/{}/{}/{}", role_name_or_id, emoji_str, guild_id.0, msg.channel_id.0, message_id))
        .map_or_else(|e| Err(CommandError(e.to_string())), |_| Ok(()))
}
fn reaction_add ( ctx : & mut Context , msg : & Message , mut args : Args ) -> CommandResult { let emoji_string = args . single :: < String > ( ) ? ; let emoji_str : & str = emoji_string . as_ref ( ) ; let emoji = { match serenity :: utils :: parse_emoji ( emoji_str ) { Some ( emoji ) => Some ( emoji ) , None => { if emoji_str . starts_with ( " " ) { let mut split = emoji_str . split ( ':' ) ; let name = split . nth ( 1 ) . ok_or ( " " ) ? ; log :: debug ! ( " " name ) ; let id = split . next ( ) . ok_or ( " " ) ? . trim_end_matches ( '>' ) ; log :: debug ! ( " " id ) ; Some ( serenity :: model :: misc :: EmojiIdentifier { id : serenity :: model :: id :: EmojiId ( id . parse :: < u64 > ( ) ? ) , name : name . to_string ( ) , } ) } else if ! emoji_str . is_ascii ( ) { None } else { return Err ( CommandError ( " " . to_string ( ) ) ) ; } } } } ; let role_id = { match args . single :: < RoleId > ( ) { Ok ( role_id ) => role_id , Err ( _ ) => RoleId ( serenity :: utils :: parse_role ( args . single :: < String > ( ) ? ) . ok_or ( " " ) ? , ) , } } ; let message = args . single :: < String > ( ) ? ; // The lazy_static will only panic if the regex itself is invalid, and therefore, shouldn't // ever panic. // regex test link: https://regex101.com/r/Rth5jE/6 // rust playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7bc300a4af839a35ec3a9c4daf9344da lazy_static ! { static ref REGEX Regex Regex new ( r"(?m)http[s]?://?(?:ptb\.|canary\.)?discord(?:app)?\.com/channels/\d*/(\d*)/(\d*)" ) expect ( " " ) } let capture = REGEX . captures ( & message ) . ok_or ( " " ) ? ; let message_id = { let id = capture . get ( 2 ) . ok_or ( " " ) ? . as_str ( ) . parse :: < u64 > ( ) ? ; MessageId ( id ) } ; let guild_id = msg . guild_id . ok_or ( " " ) ? ; let ( fancy_db , runtime_lock ) = { let data = ctx . data . read ( ) ; let fancy_db = Arc :: clone ( data . get :: < PoolContainer > ( ) . ok_or ( " " ) ? ) ; let runtime_lock = Arc :: clone ( data . get :: < TokioContainer > ( ) . ok_or ( " " ) ? , ) ; ( fancy_db , runtime_lock ) } ; { let mut tokio = runtime_lock . try_lock ( ) ? ; if let Some ( emoji_indentifier ) = emoji { log :: debug ! ( " " emoji_indentifier name emoji_indentifier id ) ; tokio . block_on ( sqlx :: query ! ( " " guild_id 0 as i64 role_id 0 as i64 message_id 0 as i64 emoji_indentifier id 0 as i64 emoji_indentifier name ) . execute ( fancy_db . pool ( ) ) ) ? ; ctx . http . create_reaction ( capture . get ( 1 ) . ok_or ( " " ) ? . as_str ( ) . parse :: < u64 > ( ) ? , message_id . 0 , & emoji_indentifier . into ( ) , ) ? ; } else { log :: debug ! ( " " emoji_str ) ; tokio . block_on ( sqlx :: query ! ( " " guild_id 0 as i64 role_id 0 as i64 message_id 0 as i64 emoji_str ) . execute ( fancy_db . pool ( ) ) ) ? ; ctx . http . create_reaction ( capture . get ( 1 ) . ok_or ( " " ) ? . as_str ( ) . parse :: < u64 > ( ) ? , message_id . 0 , & emoji_str . into ( ) , ) ? ; } } // Attempt to find role in cache, // if found, return the name of the role, // if not found, return a mention of the role. let role_name_or_id = { match role_id . to_role_cached ( & ctx ) { Some ( role ) => role . name , None => format ! ( " " role_id 0 ) , } } ; msg . channel_id . say ( & ctx . http , format ! ( " \n " role_name_or_id emoji_str guild_id 0 msg channel_id 0 message_id ) ) . map_or_else ( | e | Err ( CommandError ( e . to_string ( ) ) ) , | _ | Ok ( ( ) ) ) }
Allows you to add a reaction to a message, that a user
can click on to give them the role you specified.
Allows you to add a reaction to a message that a user can click on to give them the role you specified .
ctx
&mut Context
msg
&Message
args
Args
ctx
&mut Context
msg
&Message
args
Args