/
Kuj1
/
ds_point
Обзор
Документация
Войти
/
Kuj1
/
ds_point
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/bot.rs
359 строк
10 KB
kuj1
refactored code
20 авг 2024, 15:22
20 авг 2024, 15:22
f2bf20f
Код
Авторство
О чём код?
use std::sync::Arc; use crate::config; use crate::errors::{BotError, TextMsgResult}; use regex::Regex; use tokio::sync::broadcast::Sender; use serde::{Deserialize, Serialize}; use serenity::async_trait; use serenity::model::channel::Message; use serenity::prelude::*; use tracing::warn; pub struct NotifierBot { act_bot: Client, } impl NotifierBot { pub async fn new(config: Arc<config::Config>) -> Result<Self, BotError> { let token = config.discord_bot_token.expose_secret(); let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::DIRECT_MESSAGES | GatewayIntents::MESSAGE_CONTENT; let client = Client::builder(token, intents) .event_handler(Handler) .await?; Ok(NotifierBot { act_bot: client }) } pub async fn insert_msg_handler<H: TypeMapKey>(&mut self, sender: H::Value) { let mut data = self.act_bot.data.write().await; data.insert::<H>(sender) } pub async fn start(&mut self) -> Result<(), BotError> { self.act_bot.start().await?; Ok(()) } } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct MsgEmbed { title: String, description: String, footer: String, author: String, } impl MsgEmbed { fn new(title: String, description: String, footer: String, author: String) -> Self { Self { title, description, footer, author, } } } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct MsgForSend { channel_name: String, global_name: String, nick_name: String, server_name: String, is_bot: bool, mentions: Vec<String>, content: String, sticker_name: String, attachments: Vec<(String, String)>, message_link: String, reply_message_link: String, poll_name: String, embeds: Vec<MsgEmbed>, } #[derive(Debug, Default)] pub struct MsgForSendBuilder { channel_name: Option<String>, global_name: Option<String>, nick_name: Option<String>, server_name: Option<String>, is_bot: Option<bool>, mentions: Option<Vec<String>>, content: Option<String>, sticker_name: Option<String>, attachments: Option<Vec<(String, String)>>, message_link: Option<String>, reply_message_link: Option<String>, poll_name: Option<String>, embeds: Option<Vec<MsgEmbed>>, } impl MsgForSendBuilder { fn with_channel_name(self, channel_name: Option<String>) -> Self { Self { channel_name, ..self } } fn with_global_name(self, global_name: Option<String>) -> Self { Self { global_name, ..self } } fn with_nick_name(self, nick_name: Option<String>) -> Self { Self { nick_name, ..self } } fn with_server_name(self, server_name: Option<String>) -> Self { Self { server_name, ..self } } fn with_is_bot(self, is_bot: Option<bool>) -> Self { Self { is_bot, ..self } } fn with_mentions(self, mentions: Option<Vec<String>>) -> Self { Self { mentions, ..self } } fn with_content(self, content: Option<String>) -> Self { Self { content, ..self } } fn with_sticker_name(self, sticker_name: Option<String>) -> Self { Self { sticker_name, ..self } } fn with_attachments(self, attachments: Option<Vec<(String, String)>>) -> Self { Self { attachments, ..self } } fn with_message_link(self, message_link: Option<String>) -> Self { Self { message_link, ..self } } fn with_reply_message_link(self, reply_message_link: Option<String>) -> Self { Self { reply_message_link, ..self } } fn with_poll_name(self, poll_name: Option<String>) -> Self { Self { poll_name, ..self } } fn with_embeds(self, embeds: Option<Vec<MsgEmbed>>) -> Self { Self { embeds, ..self } } pub fn build(self) -> MsgForSend { MsgForSend { channel_name: self.channel_name.unwrap_or_default(), global_name: self.global_name.unwrap_or_default(), nick_name: self.nick_name.unwrap_or_default(), server_name: self.server_name.unwrap_or_default(), is_bot: self.is_bot.unwrap_or_default(), mentions: self.mentions.unwrap_or_default(), content: self.content.unwrap_or_default(), sticker_name: self.sticker_name.unwrap_or_default(), attachments: self.attachments.unwrap_or_default(), message_link: self.message_link.unwrap_or_default(), reply_message_link: self.reply_message_link.unwrap_or_default(), poll_name: self.poll_name.unwrap_or_default(), embeds: self.embeds.unwrap_or_default(), } } } pub struct TextMsg { channel_name: String, global_name: String, nick_name: String, server_name: String, is_bot: bool, mentions: Vec<String>, content: String, sticker_name: String, attachmets: Vec<(String, String)>, message_link: String, reply_message_link: String, poll_name: String, embeds: Vec<MsgEmbed>, } impl TextMsg { async fn new(ctx: &Context, msg: Message) -> TextMsgResult { let re_for_msg = Regex::new(r"\s(<[@|#](\W+\d+|\d+)>)|(<[@|#](\W+\d+|\d+)>)\s|(<[@|#](\W+\d+|\d+)>)") .expect("Cant parse this expression"); let channel = msg.channel(&ctx.http).await?; let guild = channel.clone().guild().unwrap_or_default(); let guild_id = guild.guild_id; let roles = guild_id.roles(&ctx.http).await?; let channel_name = guild.clone().name; let author = &msg.author; let is_bot = author.bot; let global_name = &author.global_name.clone().unwrap_or_default(); let nick_name = &author.name; let server_name = &author.nick_in(ctx, guild_id).await.unwrap_or_default(); let content = re_for_msg.replace_all(&msg.content, ""); let mut mention_roles = msg .mention_roles .iter() .map(|mention| { let mention_role = roles.get(mention); match mention_role { Some(role) => format!(" @{}", role.name), None => String::default(), } }) .collect::<Vec<String>>(); let mut mentions = msg .mentions .iter() .map(|user| format!(" @{}", user.name)) .collect::<Vec<String>>(); mentions.append(&mut mention_roles); let message_link = &msg.link(); let sticker_name = msg .sticker_items .first() .map(|x| x.name.clone()) .unwrap_or_default(); let poll_name = match &msg.poll { Some(x) => x.question.text.clone().unwrap_or(String::from("")), None => String::from(""), }; let reply_message_link = match &msg.referenced_message { Some(msg) => msg.link(), None => String::from(""), }; let mut attachment_links = Vec::with_capacity(msg.attachments.len() + 1); for attachment in msg.clone().attachments.into_iter() { let attachment_link = attachment.url; let filename = attachment.filename; attachment_links.push((filename, attachment_link)); } let embeds = msg .embeds .into_iter() .map(|embed| { let title = embed.title.unwrap_or_default(); let description = embed.description.unwrap_or_default(); let footer = match embed.footer { Some(footer) => footer.text, None => String::new(), }; let author = match embed.author { Some(author) => author.name, None => String::new(), }; MsgEmbed::new(title, description, footer, author) }) .collect::<Vec<MsgEmbed>>(); Ok(Self { channel_name, global_name: global_name.to_string(), nick_name: nick_name.to_string(), server_name: server_name.to_string(), is_bot, mentions, content: content.to_string(), sticker_name, attachmets: attachment_links, message_link: message_link.to_string(), reply_message_link, poll_name, embeds, }) } } pub struct MessageHandler; pub struct Handler; impl TypeMapKey for MessageHandler { type Value = Sender<MsgForSend>; } #[async_trait] impl EventHandler for Handler { async fn message(&self, ctx: Context, msg: Message) { let sender = { let data_read = ctx.data.read().await; data_read .get::<MessageHandler>() .expect("Expected MessageCount in TypeMap.") .clone() }; if let Ok(text_msg) = TextMsg::new(&ctx, msg).await { let for_send = MsgForSendBuilder::default() .with_channel_name(Some(text_msg.channel_name)) .with_global_name(Some(text_msg.global_name)) .with_nick_name(Some(text_msg.nick_name)) .with_server_name(Some(text_msg.server_name)) .with_is_bot(Some(text_msg.is_bot)) .with_sticker_name(Some(text_msg.sticker_name)) .with_mentions(Some(text_msg.mentions)) .with_content(Some(text_msg.content)) .with_attachments(Some(text_msg.attachmets)) .with_message_link(Some(text_msg.message_link)) .with_reply_message_link(Some(text_msg.reply_message_link)) .with_poll_name(Some(text_msg.poll_name)) .with_embeds(Some(text_msg.embeds)) .build(); sender.send(for_send).unwrap_or_else(|error| { warn!("Zero value was sended: {}", error); warn!("All channel is closed now"); 0 }); } } }