2021-12-27 17:33:09 -06:00
|
|
|
use std::{collections::HashMap, env, fs::File, io::Read, sync::Arc};
|
2021-12-26 15:13:09 -06:00
|
|
|
|
2021-12-26 16:05:53 -06:00
|
|
|
use serenity::{
|
|
|
|
async_trait,
|
2021-12-27 11:24:31 -06:00
|
|
|
futures::StreamExt,
|
2021-12-26 16:05:53 -06:00
|
|
|
http::Http,
|
|
|
|
model::{
|
|
|
|
channel::Message,
|
2021-12-27 17:33:09 -06:00
|
|
|
guild::Member,
|
2021-12-26 16:05:53 -06:00
|
|
|
id::{ChannelId, UserId},
|
2021-12-27 17:33:09 -06:00
|
|
|
prelude::Ready,
|
|
|
|
webhook::Webhook,
|
2021-12-26 16:05:53 -06:00
|
|
|
},
|
|
|
|
prelude::*,
|
2021-12-27 11:24:31 -06:00
|
|
|
Client as DiscordClient,
|
|
|
|
};
|
|
|
|
|
|
|
|
use irc::{
|
|
|
|
client::{data::Config, Client as IrcClient, Sender},
|
|
|
|
proto::Command,
|
2021-12-26 16:05:53 -06:00
|
|
|
};
|
2021-12-26 15:13:09 -06:00
|
|
|
|
2022-01-06 13:28:20 -06:00
|
|
|
use lazy_static::lazy_static;
|
2022-01-06 13:29:12 -06:00
|
|
|
use regex::Regex;
|
2022-01-06 13:28:20 -06:00
|
|
|
|
2022-01-04 17:05:29 -06:00
|
|
|
use serde::Deserialize;
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct DircordConfig {
|
|
|
|
token: String,
|
|
|
|
webhook: Option<String>,
|
|
|
|
nickname: Option<String>,
|
|
|
|
server: String,
|
|
|
|
port: Option<u16>,
|
|
|
|
channels: Vec<String>,
|
|
|
|
mode: Option<String>,
|
|
|
|
tls: Option<bool>,
|
|
|
|
}
|
2021-12-27 13:49:54 -06:00
|
|
|
|
2021-12-26 15:13:09 -06:00
|
|
|
struct Handler;
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl EventHandler for Handler {
|
|
|
|
async fn message(&self, ctx: Context, msg: Message) {
|
|
|
|
let nick = {
|
|
|
|
if let Some(member) = msg.member {
|
|
|
|
match member.nick {
|
|
|
|
Some(n) => n,
|
2021-12-26 16:05:53 -06:00
|
|
|
None => msg.author.name,
|
2021-12-26 15:13:09 -06:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
msg.author.name
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-01-15 11:15:08 -06:00
|
|
|
let byte = nick.chars().nth(0).unwrap() as u8;
|
2022-01-05 12:14:58 -06:00
|
|
|
|
|
|
|
let colour_index = (byte as usize + nick.len()) % 12;
|
|
|
|
let formatted = format!("\x03{:02}", colour_index);
|
|
|
|
|
|
|
|
let mut new_nick = String::with_capacity(nick.len());
|
|
|
|
new_nick.push_str(&formatted);
|
|
|
|
|
|
|
|
for char in nick.chars() {
|
|
|
|
new_nick.push(char);
|
|
|
|
new_nick.push('\u{200B}');
|
|
|
|
new_nick.push_str(&formatted);
|
|
|
|
}
|
|
|
|
new_nick.push_str("\x030");
|
|
|
|
|
2022-01-15 12:32:27 -06:00
|
|
|
let (user_id, sender, members) = {
|
2021-12-26 15:35:49 -06:00
|
|
|
let data = ctx.data.read().await;
|
|
|
|
|
2021-12-26 16:05:53 -06:00
|
|
|
let user_id = data.get::<UserIdKey>().unwrap().to_owned();
|
2021-12-27 13:28:35 -06:00
|
|
|
let sender = data.get::<SenderKey>().unwrap().to_owned();
|
2022-01-15 12:32:27 -06:00
|
|
|
let members = data.get::<MembersKey>().unwrap().to_owned();
|
2021-12-26 15:35:49 -06:00
|
|
|
|
2022-01-15 12:32:27 -06:00
|
|
|
(user_id, sender, members)
|
2021-12-26 15:35:49 -06:00
|
|
|
};
|
2021-12-27 17:33:09 -06:00
|
|
|
|
2022-01-05 13:26:19 -06:00
|
|
|
let attachments: Vec<String> = msg.attachments.iter().map(|a| a.url.clone()).collect();
|
|
|
|
|
2022-01-15 12:32:27 -06:00
|
|
|
lazy_static! {
|
|
|
|
static ref PING_RE_1: Regex = Regex::new(r"<@[0-9]+>").unwrap();
|
|
|
|
static ref PING_RE_2: Regex = Regex::new(r"<@![0-9]+>").unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut id_cache: HashMap<u64, String> = HashMap::new();
|
|
|
|
|
|
|
|
if PING_RE_1.is_match(&msg.content) {
|
|
|
|
for mat in PING_RE_1.find_iter(&msg.content) {
|
2022-01-15 12:32:47 -06:00
|
|
|
let slice = &msg.content[mat.start() + 2..mat.end() - 1];
|
2022-01-15 12:32:27 -06:00
|
|
|
let id = slice.parse::<u64>().unwrap();
|
|
|
|
for member in &*members {
|
|
|
|
if id == member.user.id.0 {
|
|
|
|
let nick = {
|
|
|
|
match &member.nick {
|
|
|
|
Some(n) => n.clone(),
|
2022-01-15 12:32:47 -06:00
|
|
|
None => member.user.name.clone(),
|
2022-01-15 12:32:27 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
id_cache.insert(id, nick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if PING_RE_2.is_match(&msg.content) {
|
|
|
|
for mat in PING_RE_2.find_iter(&msg.content) {
|
2022-01-15 12:32:47 -06:00
|
|
|
let slice = &msg.content[mat.start() + 3..mat.end() - 1];
|
2022-01-15 12:32:27 -06:00
|
|
|
let id = slice.parse::<u64>().unwrap();
|
|
|
|
for member in &*members {
|
|
|
|
if id == member.user.id.0 {
|
|
|
|
let nick = {
|
|
|
|
match &member.nick {
|
|
|
|
Some(n) => n.clone(),
|
2022-01-15 12:32:47 -06:00
|
|
|
None => member.user.name.clone(),
|
|
|
|
}
|
2022-01-15 12:32:27 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
id_cache.insert(id, nick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut computed = msg.content.clone();
|
|
|
|
|
|
|
|
for mat in PING_RE_1.find_iter(&msg.content) {
|
2022-01-15 12:32:47 -06:00
|
|
|
let slice = &msg.content[mat.start() + 2..mat.end() - 1];
|
2022-01-15 12:32:27 -06:00
|
|
|
let id = slice.parse::<u64>().unwrap();
|
|
|
|
if let Some(cached) = id_cache.get(&id) {
|
2022-01-15 12:32:47 -06:00
|
|
|
computed = PING_RE_1
|
|
|
|
.replace(&computed, format!("@{}", cached))
|
|
|
|
.to_string();
|
2022-01-15 12:32:27 -06:00
|
|
|
}
|
|
|
|
}
|
2022-01-07 11:47:54 -06:00
|
|
|
|
2022-01-15 12:32:27 -06:00
|
|
|
for mat in PING_RE_2.find_iter(&msg.content) {
|
2022-01-15 12:32:47 -06:00
|
|
|
let slice = &msg.content[mat.start() + 3..mat.end() - 1];
|
2022-01-15 12:32:27 -06:00
|
|
|
let id = slice.parse::<u64>().unwrap();
|
|
|
|
if let Some(cached) = id_cache.get(&id) {
|
2022-01-15 12:32:47 -06:00
|
|
|
computed = PING_RE_2
|
|
|
|
.replace(&computed, format!("@{}", cached))
|
|
|
|
.to_string();
|
2022-01-15 12:32:27 -06:00
|
|
|
}
|
|
|
|
}
|
2022-01-07 11:47:54 -06:00
|
|
|
|
2021-12-27 13:28:35 -06:00
|
|
|
if user_id != msg.author.id && !msg.author.bot {
|
2022-01-15 12:32:27 -06:00
|
|
|
send_irc_message(&sender, &format!("<{}> {}", new_nick, computed))
|
2021-12-27 13:28:35 -06:00
|
|
|
.await
|
|
|
|
.unwrap();
|
2022-01-05 13:26:19 -06:00
|
|
|
for attachment in attachments {
|
|
|
|
send_irc_message(&sender, &format!("<{}> {}", new_nick, attachment))
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
}
|
2021-12-27 13:28:35 -06:00
|
|
|
}
|
2021-12-26 16:05:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn ready(&self, ctx: Context, info: Ready) {
|
|
|
|
let id = info.user.id;
|
|
|
|
|
|
|
|
let mut data = ctx.data.write().await;
|
|
|
|
data.insert::<UserIdKey>(id);
|
2021-12-26 15:13:09 -06:00
|
|
|
}
|
2021-12-26 14:04:47 -06:00
|
|
|
}
|
2021-12-26 15:13:09 -06:00
|
|
|
|
2021-12-26 15:35:49 -06:00
|
|
|
struct HttpKey;
|
|
|
|
struct ChannelIdKey;
|
2021-12-26 16:05:53 -06:00
|
|
|
struct UserIdKey;
|
2021-12-27 11:24:31 -06:00
|
|
|
struct SenderKey;
|
2022-01-15 12:32:27 -06:00
|
|
|
struct MembersKey;
|
2021-12-26 15:35:49 -06:00
|
|
|
|
|
|
|
impl TypeMapKey for HttpKey {
|
|
|
|
type Value = Arc<Http>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeMapKey for ChannelIdKey {
|
|
|
|
type Value = ChannelId;
|
|
|
|
}
|
|
|
|
|
2021-12-26 16:05:53 -06:00
|
|
|
impl TypeMapKey for UserIdKey {
|
|
|
|
type Value = UserId;
|
|
|
|
}
|
|
|
|
|
2021-12-27 11:24:31 -06:00
|
|
|
impl TypeMapKey for SenderKey {
|
|
|
|
type Value = Sender;
|
|
|
|
}
|
|
|
|
|
2022-01-15 12:32:27 -06:00
|
|
|
impl TypeMapKey for MembersKey {
|
|
|
|
type Value = Arc<Vec<Member>>;
|
|
|
|
}
|
|
|
|
|
2021-12-26 15:13:09 -06:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> anyhow::Result<()> {
|
2022-01-04 17:05:29 -06:00
|
|
|
let filename = env::args().nth(1).unwrap_or(String::from("config.toml"));
|
2021-12-27 13:49:54 -06:00
|
|
|
let mut data = String::new();
|
|
|
|
File::open(filename)?.read_to_string(&mut data)?;
|
|
|
|
|
2022-01-04 17:05:29 -06:00
|
|
|
let conf: DircordConfig = toml::from_str(&data)?;
|
2021-12-26 15:13:09 -06:00
|
|
|
|
2022-01-04 17:05:29 -06:00
|
|
|
let mut discord_client = DiscordClient::builder(&conf.token)
|
2021-12-27 11:24:31 -06:00
|
|
|
.event_handler(Handler)
|
|
|
|
.await?;
|
2021-12-26 15:13:09 -06:00
|
|
|
|
|
|
|
let channel_id = ChannelId(831255708875751477);
|
|
|
|
|
2021-12-27 11:24:31 -06:00
|
|
|
let config = Config {
|
2022-01-04 17:05:29 -06:00
|
|
|
nickname: conf.nickname,
|
|
|
|
server: Some(conf.server),
|
|
|
|
port: conf.port,
|
|
|
|
channels: conf.channels,
|
|
|
|
use_tls: conf.tls,
|
|
|
|
umodes: conf.mode,
|
2021-12-27 11:24:31 -06:00
|
|
|
..Config::default()
|
|
|
|
};
|
|
|
|
|
2021-12-27 13:28:35 -06:00
|
|
|
let irc_client = IrcClient::from_config(config).await?;
|
2021-12-27 11:24:31 -06:00
|
|
|
|
|
|
|
let http = discord_client.cache_and_http.http.clone();
|
|
|
|
|
2022-01-15 12:32:47 -06:00
|
|
|
let members = Arc::new(
|
|
|
|
channel_id
|
|
|
|
.to_channel(discord_client.cache_and_http.clone())
|
|
|
|
.await?
|
|
|
|
.guild()
|
|
|
|
.unwrap() // we can panic here because if it's not a guild channel then the bot shouldn't even work
|
|
|
|
.guild_id
|
|
|
|
.members(&http, None, None)
|
|
|
|
.await?,
|
|
|
|
);
|
2021-12-27 17:33:09 -06:00
|
|
|
|
2021-12-26 15:35:49 -06:00
|
|
|
{
|
2021-12-27 11:24:31 -06:00
|
|
|
let mut data = discord_client.data.write().await;
|
|
|
|
data.insert::<SenderKey>(irc_client.sender());
|
2022-01-15 12:32:27 -06:00
|
|
|
data.insert::<MembersKey>(members.clone());
|
2021-12-26 15:35:49 -06:00
|
|
|
}
|
|
|
|
|
2022-01-04 17:05:29 -06:00
|
|
|
let webhook = parse_webhook_url(http.clone(), conf.webhook)
|
2021-12-27 17:33:09 -06:00
|
|
|
.await
|
|
|
|
.expect("Invalid webhook URL");
|
2021-12-27 14:46:12 -06:00
|
|
|
|
2021-12-27 11:24:31 -06:00
|
|
|
tokio::spawn(async move {
|
2021-12-27 17:33:09 -06:00
|
|
|
irc_loop(irc_client, http, channel_id, webhook, members)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2021-12-27 11:24:31 -06:00
|
|
|
});
|
|
|
|
discord_client.start().await?;
|
2021-12-26 15:13:09 -06:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-12-27 13:28:35 -06:00
|
|
|
async fn send_irc_message(sender: &Sender, content: &str) -> anyhow::Result<()> {
|
|
|
|
sender.send_privmsg("#no-normies", content)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-12-27 11:24:31 -06:00
|
|
|
async fn irc_loop(
|
|
|
|
mut client: IrcClient,
|
|
|
|
http: Arc<Http>,
|
|
|
|
channel_id: ChannelId,
|
2021-12-27 17:33:09 -06:00
|
|
|
webhook: Option<Webhook>,
|
2022-01-15 12:32:27 -06:00
|
|
|
members: Arc<Vec<Member>>,
|
2021-12-27 11:24:31 -06:00
|
|
|
) -> anyhow::Result<()> {
|
2021-12-27 17:33:09 -06:00
|
|
|
let mut avatar_cache: HashMap<String, Option<String>> = HashMap::new();
|
2022-01-06 13:28:20 -06:00
|
|
|
let mut id_cache: HashMap<String, Option<u64>> = HashMap::new();
|
|
|
|
|
|
|
|
lazy_static! {
|
2022-01-06 13:32:17 -06:00
|
|
|
static ref PING_NICK_1: Regex = Regex::new(r"^[\w+]+(:|,)").unwrap();
|
2022-01-07 11:31:52 -06:00
|
|
|
static ref PING_RE_2: Regex = Regex::new(r"@[^0-9\s]+").unwrap();
|
2022-01-06 13:28:20 -06:00
|
|
|
}
|
2021-12-27 17:33:09 -06:00
|
|
|
|
2021-12-27 11:24:31 -06:00
|
|
|
client.identify()?;
|
|
|
|
let mut stream = client.stream()?;
|
2021-12-27 17:33:09 -06:00
|
|
|
|
2021-12-27 11:24:31 -06:00
|
|
|
while let Some(orig_message) = stream.next().await.transpose()? {
|
|
|
|
print!("{}", orig_message);
|
2021-12-27 13:28:35 -06:00
|
|
|
if let Command::PRIVMSG(_, ref message) = orig_message.command {
|
2021-12-27 11:24:31 -06:00
|
|
|
let nickname = orig_message.source_nickname().unwrap();
|
2022-01-07 11:31:52 -06:00
|
|
|
let mut mentioned_1: Option<u64> = None;
|
2022-01-06 13:29:12 -06:00
|
|
|
if PING_NICK_1.is_match(message) {
|
|
|
|
if let Some(mat) = PING_NICK_1.find(message) {
|
2022-01-07 11:33:25 -06:00
|
|
|
let slice = &message[mat.start()..mat.end() - 1];
|
2022-01-07 11:31:52 -06:00
|
|
|
if let Some(id) = id_cache.get(slice) {
|
|
|
|
mentioned_1 = id.to_owned();
|
|
|
|
} else {
|
2022-01-06 13:29:12 -06:00
|
|
|
let mut found = false;
|
2022-01-15 12:32:27 -06:00
|
|
|
for member in &*members {
|
2022-01-06 13:29:12 -06:00
|
|
|
let nick = match &member.nick {
|
|
|
|
Some(s) => s.to_owned(),
|
2022-01-07 11:33:25 -06:00
|
|
|
None => member.user.name.clone(),
|
2022-01-06 13:29:12 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
if nick == slice {
|
|
|
|
found = true;
|
|
|
|
let id = member.user.id.0;
|
2022-01-07 11:31:52 -06:00
|
|
|
mentioned_1 = Some(id);
|
2022-01-06 13:28:20 -06:00
|
|
|
}
|
2022-01-06 13:29:12 -06:00
|
|
|
}
|
2022-01-06 13:28:20 -06:00
|
|
|
|
2022-01-06 13:29:12 -06:00
|
|
|
if !found {
|
2022-01-07 11:31:52 -06:00
|
|
|
mentioned_1 = None;
|
2022-01-06 13:28:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-06 13:29:12 -06:00
|
|
|
}
|
2022-01-06 13:49:41 -06:00
|
|
|
if PING_RE_2.is_match(message) {
|
2022-01-07 11:31:52 -06:00
|
|
|
for mat in PING_RE_2.find_iter(message) {
|
2022-01-07 11:33:25 -06:00
|
|
|
let slice = &message[mat.start() + 1..mat.end()];
|
2022-01-07 11:31:52 -06:00
|
|
|
dbg!(slice);
|
2022-01-06 13:49:41 -06:00
|
|
|
if id_cache.get(slice).is_none() {
|
|
|
|
let mut found = false;
|
2022-01-15 12:32:27 -06:00
|
|
|
for member in &*members {
|
2022-01-06 13:49:41 -06:00
|
|
|
let nick = match &member.nick {
|
|
|
|
Some(s) => s.to_owned(),
|
|
|
|
None => member.user.name.clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
if nick == slice {
|
|
|
|
found = true;
|
|
|
|
let id = member.user.id.0;
|
2022-01-07 11:31:52 -06:00
|
|
|
id_cache.insert(slice.to_string(), Some(id));
|
2022-01-06 13:49:41 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
2022-01-07 11:31:52 -06:00
|
|
|
id_cache.insert(slice.to_string(), None);
|
2022-01-06 13:49:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-27 16:41:27 -06:00
|
|
|
if let Some(ref webhook) = webhook {
|
2021-12-27 17:33:09 -06:00
|
|
|
if avatar_cache.get(nickname).is_none() {
|
|
|
|
let mut found = false;
|
2022-01-15 12:32:27 -06:00
|
|
|
for member in &*members {
|
2021-12-27 17:33:09 -06:00
|
|
|
let nick = match &member.nick {
|
|
|
|
Some(s) => s.to_owned(),
|
|
|
|
None => member.user.name.clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
if nick == nickname {
|
|
|
|
found = true;
|
|
|
|
let avatar_url = member.user.avatar_url();
|
|
|
|
avatar_cache.insert(nickname.to_string(), avatar_url);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
avatar_cache.insert(nickname.to_string(), None); // user is not in the guild
|
|
|
|
}
|
|
|
|
}
|
2022-01-06 13:28:20 -06:00
|
|
|
|
2021-12-27 17:33:09 -06:00
|
|
|
webhook
|
|
|
|
.execute(&http, false, |w| {
|
|
|
|
if let Some(cached) = avatar_cache.get(nickname) {
|
|
|
|
if let &Some(ref url) = cached {
|
|
|
|
w.avatar_url(url);
|
|
|
|
}
|
|
|
|
}
|
2022-01-07 11:31:52 -06:00
|
|
|
|
|
|
|
let mut computed = message.to_string();
|
2022-01-07 11:33:25 -06:00
|
|
|
|
2022-01-07 11:31:52 -06:00
|
|
|
for mat in PING_RE_2.find_iter(message) {
|
2022-01-07 11:33:25 -06:00
|
|
|
let slice = &message[mat.start() + 1..mat.end()];
|
2022-01-07 11:31:52 -06:00
|
|
|
if let Some(cached) = id_cache.get(slice) {
|
|
|
|
if let &Some(id) = cached {
|
2022-01-07 11:33:25 -06:00
|
|
|
computed = PING_RE_2
|
|
|
|
.replace(&computed, format!("<@{}>", id))
|
|
|
|
.to_string();
|
2022-01-07 11:31:52 -06:00
|
|
|
}
|
2022-01-06 13:28:20 -06:00
|
|
|
}
|
|
|
|
}
|
2022-01-07 11:31:52 -06:00
|
|
|
|
|
|
|
if let Some(id) = mentioned_1 {
|
2022-01-07 11:33:25 -06:00
|
|
|
computed = PING_NICK_1
|
|
|
|
.replace(&computed, format!("<@{}>", id))
|
|
|
|
.to_string();
|
2022-01-07 11:31:52 -06:00
|
|
|
}
|
|
|
|
|
2021-12-27 17:33:09 -06:00
|
|
|
w.username(nickname);
|
2022-01-07 11:31:52 -06:00
|
|
|
w.content(computed);
|
2021-12-27 17:33:09 -06:00
|
|
|
w
|
|
|
|
})
|
|
|
|
.await?;
|
2021-12-27 16:41:27 -06:00
|
|
|
} else {
|
2022-01-07 11:33:25 -06:00
|
|
|
let mut computed = message.to_string();
|
2022-01-07 11:31:52 -06:00
|
|
|
|
2022-01-07 11:33:25 -06:00
|
|
|
for mat in PING_RE_2.find_iter(message) {
|
|
|
|
let slice = &message[mat.start() + 1..mat.end()];
|
|
|
|
if let Some(cached) = id_cache.get(slice) {
|
|
|
|
if let &Some(id) = cached {
|
|
|
|
computed = PING_RE_2
|
|
|
|
.replace(&computed, format!("<@{}>", id))
|
|
|
|
.to_string();
|
2022-01-07 11:31:52 -06:00
|
|
|
}
|
2022-01-07 11:33:25 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(id) = mentioned_1 {
|
|
|
|
computed = PING_NICK_1
|
|
|
|
.replace(&computed, format!("<@{}>", id))
|
|
|
|
.to_string();
|
|
|
|
}
|
2022-01-07 11:31:52 -06:00
|
|
|
|
|
|
|
channel_id
|
|
|
|
.say(&http, format!("<{}> {}", nickname, computed))
|
|
|
|
.await?;
|
2021-12-27 16:41:27 -06:00
|
|
|
}
|
2022-01-03 15:19:53 -06:00
|
|
|
} else if let Command::JOIN(_, _, _) = orig_message.command {
|
|
|
|
let nickname = orig_message.source_nickname().unwrap();
|
|
|
|
channel_id
|
|
|
|
.say(&http, format!("*{}* has joined the channel", nickname))
|
|
|
|
.await?;
|
2022-01-03 15:20:03 -06:00
|
|
|
} else if let Command::PART(_, ref reason) | Command::QUIT(ref reason) =
|
|
|
|
orig_message.command
|
|
|
|
{
|
2022-01-03 15:19:53 -06:00
|
|
|
let nickname = orig_message.source_nickname().unwrap();
|
2022-01-03 15:20:03 -06:00
|
|
|
let reason = reason
|
|
|
|
.as_ref()
|
|
|
|
.unwrap_or(&String::from("Connection closed"))
|
|
|
|
.to_string();
|
2022-01-03 15:19:53 -06:00
|
|
|
channel_id
|
|
|
|
.say(&http, format!("*{}* has quit ({})", nickname, reason))
|
|
|
|
.await?;
|
2021-12-27 11:24:31 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
2021-12-26 16:05:53 -06:00
|
|
|
}
|
2021-12-27 14:46:12 -06:00
|
|
|
|
2021-12-27 17:33:09 -06:00
|
|
|
async fn parse_webhook_url(
|
|
|
|
http: Arc<Http>,
|
|
|
|
url: Option<String>,
|
|
|
|
) -> anyhow::Result<Option<Webhook>> {
|
2021-12-27 14:46:12 -06:00
|
|
|
if let Some(url) = url {
|
|
|
|
let url = url.trim_start_matches("https://discord.com/api/webhooks/");
|
|
|
|
let split = url.split("/").collect::<Vec<&str>>();
|
2021-12-27 16:44:34 -06:00
|
|
|
let id = split[0].parse::<u64>()?;
|
2021-12-27 14:46:12 -06:00
|
|
|
let token = split[1].to_string();
|
2021-12-27 16:44:34 -06:00
|
|
|
let webhook = http.get_webhook_with_token(id, &token).await?;
|
|
|
|
Ok(Some(webhook))
|
2021-12-27 14:46:12 -06:00
|
|
|
} else {
|
2021-12-27 16:44:34 -06:00
|
|
|
Ok(None)
|
2021-12-27 14:46:12 -06:00
|
|
|
}
|
2021-12-27 17:33:09 -06:00
|
|
|
}
|