|
1 |
| -use std::fmt::Write; |
| 1 | +use std::{convert::TryFrom, fmt::Write}; |
2 | 2 |
|
3 |
| -use anyhow::Result; |
| 3 | +use anyhow::{anyhow, Result}; |
4 | 4 | use chrono::DateTime;
|
| 5 | +use futures_util::io::AsyncReadExt; |
| 6 | +use http::uri::Uri; |
| 7 | +use lazy_static::lazy_static; |
5 | 8 | use rand::seq::SliceRandom;
|
| 9 | +use regex::Regex; |
| 10 | +use twilight::model::channel::ReactionType; |
6 | 11 |
|
7 |
| -use crate::model::{MessageContext, Response}; |
| 12 | +use crate::model::{MessageContext, Response, ResponseReaction}; |
8 | 13 |
|
9 | 14 | const HELP_TEXT: &str = include_str!("../../help.txt");
|
10 | 15 |
|
| 16 | +lazy_static! { |
| 17 | + static ref EMOJI: Regex = Regex::new("<:([[:word:]]+):([[:digit:]]+)>").unwrap(); |
| 18 | +} |
| 19 | + |
11 | 20 | pub async fn avatar(context: &mut MessageContext) -> Result<Response> {
|
12 | 21 | let found_user = context.find_member().await?;
|
13 | 22 |
|
@@ -79,3 +88,62 @@ pub async fn shuffle(context: &mut MessageContext) -> Result<Response> {
|
79 | 88 | let reply = context.reply(content).await?;
|
80 | 89 | Ok(Response::Message(reply))
|
81 | 90 | }
|
| 91 | + |
| 92 | +pub async fn steal(context: &mut MessageContext) -> Result<Response> { |
| 93 | + if let Some(emoji) = context.next() { |
| 94 | + // create variables that hold the chain of information priority |
| 95 | + let mut uri: Option<Uri> = Uri::try_from(&emoji).ok(); |
| 96 | + let mut name: Option<String> = None; |
| 97 | + |
| 98 | + // set the uri and name from a custom emoji match |
| 99 | + if uri.is_none() { |
| 100 | + let caps = EMOJI.captures(&emoji).ok_or_else(|| anyhow!("No match."))?; |
| 101 | + let formatted = format!( |
| 102 | + "https://cdn.discordapp.com/emojis/{}.png?v=1", |
| 103 | + caps.get(2).ok_or_else(|| anyhow!("no match 2"))?.as_str() |
| 104 | + ); |
| 105 | + |
| 106 | + uri = Uri::try_from(formatted).ok(); |
| 107 | + name = caps.get(1).map(|m| String::from(m.as_str())); |
| 108 | + } |
| 109 | + |
| 110 | + // override the name if there is another argument |
| 111 | + if let Some(arg_name) = context.next() { |
| 112 | + name = Some(arg_name); |
| 113 | + } |
| 114 | + |
| 115 | + // default the name to emoji if none |
| 116 | + if name.is_none() { |
| 117 | + name = Some("emoji".into()); |
| 118 | + } |
| 119 | + |
| 120 | + // upload the emoji if everything checks out |
| 121 | + if uri.is_some() && name.is_some() { |
| 122 | + let mut resp = isahc::get_async(uri.unwrap()).await?; |
| 123 | + let mut buffer: Vec<u8> = Vec::new(); |
| 124 | + resp.body_mut().read_to_end(&mut buffer).await?; |
| 125 | + |
| 126 | + let emoji = context |
| 127 | + .http |
| 128 | + .create_emoji( |
| 129 | + context.message.guild_id.unwrap(), |
| 130 | + name.unwrap(), |
| 131 | + format!("data:image/png;base64,{}", base64::encode(buffer)), |
| 132 | + ) |
| 133 | + .await?; |
| 134 | + |
| 135 | + context.react(ResponseReaction::Success.value()).await?; |
| 136 | + context |
| 137 | + .react(ReactionType::Custom { |
| 138 | + animated: emoji.animated, |
| 139 | + id: emoji.id, |
| 140 | + name: Some(emoji.name), |
| 141 | + }) |
| 142 | + .await?; |
| 143 | + return Ok(Response::Reaction); |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + let reply = context.reply("USAGE: katze steal <emoji> [<name>]").await?; |
| 148 | + Ok(Response::Message(reply)) |
| 149 | +} |
0 commit comments