feat: WIP
This commit is contained in:
parent
6f2b15493d
commit
358fe2a9ce
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -379,10 +379,12 @@ dependencies = [
|
||||
"dotenvy",
|
||||
"openssl",
|
||||
"postgres-openssl",
|
||||
"rand",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"serenity",
|
||||
"serial_test",
|
||||
"tokio",
|
||||
@ -391,6 +393,7 @@ dependencies = [
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1856,6 +1859,19 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serenity"
|
||||
version = "0.12.0"
|
||||
@ -2392,6 +2408,12 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
|
@ -8,6 +8,7 @@ default-run = "botdiscord"
|
||||
|
||||
[dependencies]
|
||||
serde = "1.0"
|
||||
serde_yaml = "0.9"
|
||||
uuid = { version = "1.4", features = ["v4", "serde"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] }
|
||||
@ -40,6 +41,8 @@ serenity = { version = "0.12", default-features = false, features = [
|
||||
"cache",
|
||||
] }
|
||||
tokio = { version = "1.35", features = ["macros", "rt-multi-thread"] }
|
||||
rand = "0.8.5"
|
||||
walkdir = "2.4.0"
|
||||
|
||||
|
||||
[[bin]]
|
||||
|
@ -1,7 +1,17 @@
|
||||
use rand::Rng;
|
||||
use serenity::prelude::*;
|
||||
use serenity::{
|
||||
all::{Message, Ready},
|
||||
async_trait,
|
||||
client::{Context, EventHandler},
|
||||
builder::{CreateAttachment, CreateMessage},
|
||||
client::Context,
|
||||
};
|
||||
use tokio::fs::File;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
use crate::{
|
||||
config::ConfigGlobal,
|
||||
img::config_file::{ConfigImgGlobal, KeyWordItem},
|
||||
};
|
||||
|
||||
pub struct Handler;
|
||||
@ -9,7 +19,7 @@ pub struct Handler;
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn message(&self, ctx: Context, msg: Message) {
|
||||
if msg.author.bot {
|
||||
if msg.author.bot || msg.content.starts_with("!") {
|
||||
return;
|
||||
}
|
||||
if msg.content == "&ping" {
|
||||
@ -18,6 +28,64 @@ impl EventHandler for Handler {
|
||||
}
|
||||
return;
|
||||
}
|
||||
let (config_img, config) = {
|
||||
let data_read = ctx.data.read().await;
|
||||
let config_img = data_read
|
||||
.get::<ConfigImgGlobal>()
|
||||
.expect("Config img not found")
|
||||
.clone();
|
||||
let config = data_read
|
||||
.get::<ConfigGlobal>()
|
||||
.expect("Main config not found")
|
||||
.clone();
|
||||
(config_img, config)
|
||||
};
|
||||
let mut rng = rand::thread_rng();
|
||||
let folder_container = match config_img
|
||||
.keyword
|
||||
.iter()
|
||||
.find(|keyword| keyword.does_value_match(msg.content.clone()))
|
||||
{
|
||||
Some(keyword_matching) => {
|
||||
println!("{} match {:?}", msg.content, keyword_matching);
|
||||
let keyword_path = match keyword_matching.path.len() {
|
||||
0 => keyword_matching.path[0].clone(),
|
||||
_ => {
|
||||
let id = rng.gen_range(0..keyword_matching.path.len());
|
||||
keyword_matching.path[id].clone()
|
||||
}
|
||||
};
|
||||
|
||||
keyword_path.clone()
|
||||
}
|
||||
None => return,
|
||||
};
|
||||
let path = format!("{}/{}", config.image.path.clone(), folder_container);
|
||||
let file_folder = KeyWordItem::output_folder_content(path.clone());
|
||||
let id_rand: usize = rng.gen_range(0..file_folder.len());
|
||||
let filename = match file_folder.get(id_rand) {
|
||||
Some(file) => file.file_name().to_str().unwrap(),
|
||||
None => return,
|
||||
};
|
||||
let file_path = format!("{}/{}", path, filename.clone());
|
||||
let file = match File::open(file_path).await {
|
||||
Ok(file) => file,
|
||||
Err(why) => {
|
||||
println!("Error opening file: {:?}", why);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let attachment = match CreateAttachment::file(&file, filename).await {
|
||||
Ok(attachment) => attachment,
|
||||
Err(why) => {
|
||||
println!("Error creating attachment: {:?}", why);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let builder = CreateMessage::new().add_file(attachment);
|
||||
if let Err(why) = msg.channel_id.send_message(&ctx.http, builder).await {
|
||||
println!("Error sending message: {:?}", why);
|
||||
}
|
||||
}
|
||||
|
||||
async fn ready(&self, _: Context, ready: Ready) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::cmd::{help::HELP, ping::PING_COMMAND};
|
||||
use super::handler::Handler;
|
||||
use crate::config::Config;
|
||||
use crate::config::{Config, ConfigGlobal};
|
||||
use crate::img::config_file::{ConfigFile, ConfigImgGlobal};
|
||||
use serenity::framework::standard::Configuration;
|
||||
use serenity::{
|
||||
all::GatewayIntents,
|
||||
@ -9,6 +10,7 @@ use serenity::{
|
||||
Client,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
#[group]
|
||||
@ -23,6 +25,23 @@ pub fn start_bot(config: Config) {
|
||||
let local = tokio::task::LocalSet::new();
|
||||
let _ = local
|
||||
.run_until(async move {
|
||||
let config_img = match fs::read_to_string(format!(
|
||||
"{}/config.yaml",
|
||||
config.image.path
|
||||
)) {
|
||||
Ok(content) => content,
|
||||
Err(err) => {
|
||||
println!("Error while opening config.yaml : {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let config_parsed = match ConfigFile::parse_config(config_img) {
|
||||
Ok(config) => config,
|
||||
Err(err) => {
|
||||
println!("Error while parsing config.yaml : {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let intents = GatewayIntents::GUILD_MESSAGES
|
||||
| GatewayIntents::DIRECT_MESSAGES
|
||||
| GatewayIntents::MESSAGE_CONTENT
|
||||
@ -53,7 +72,7 @@ pub fn start_bot(config: Config) {
|
||||
framework.configure(
|
||||
Configuration::new()
|
||||
.with_whitespace(true)
|
||||
.prefix(config.prefix)
|
||||
.prefix(config.prefix.clone())
|
||||
.owners(owners),
|
||||
);
|
||||
|
||||
@ -62,6 +81,14 @@ pub fn start_bot(config: Config) {
|
||||
.framework(framework)
|
||||
.await
|
||||
.expect("Err creating client");
|
||||
|
||||
{
|
||||
// Open the data lock in write mode, so keys can be inserted to it.
|
||||
let mut data = client.data.write().await;
|
||||
|
||||
data.insert::<ConfigImgGlobal>(config_parsed.clone());
|
||||
data.insert::<ConfigGlobal>(config.clone());
|
||||
}
|
||||
if let Err(why) = client.start().await {
|
||||
println!("Client error: {why:?}");
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use dotenvy::dotenv;
|
||||
use serde::Deserialize;
|
||||
use serenity::prelude::TypeMapKey;
|
||||
use std::env;
|
||||
use std::fs::read_to_string;
|
||||
use std::path::PathBuf;
|
||||
@ -22,6 +23,12 @@ const RUST_ENV: &str = "RUST_ENV";
|
||||
|
||||
const PORT: &str = "PORT";
|
||||
|
||||
pub struct ConfigGlobal;
|
||||
|
||||
impl TypeMapKey for ConfigGlobal {
|
||||
type Value = Config;
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct Config {
|
||||
pub bot_name: String,
|
||||
|
64
src/img/config_file.rs
Normal file
64
src/img/config_file.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use serenity::prelude::TypeMapKey;
|
||||
use std::fmt::Debug;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct KeyWordItem {
|
||||
pub value: Vec<String>,
|
||||
pub path: Vec<String>,
|
||||
}
|
||||
|
||||
impl KeyWordItem {
|
||||
pub fn does_value_match(&self, haystack: String) -> bool {
|
||||
self.value.clone().into_iter().any(|val| {
|
||||
let re = Regex::new(&val).unwrap();
|
||||
re.is_match(&haystack)
|
||||
})
|
||||
}
|
||||
pub fn output_folder_content(path: String) -> Vec<DirEntry> {
|
||||
let file_folder: Vec<DirEntry> = WalkDir::new(&path)
|
||||
.into_iter()
|
||||
.filter_entry(|_e| true)
|
||||
.filter(|e| {
|
||||
if let Some(file) = &e.as_ref().ok() {
|
||||
return !file.metadata().unwrap().is_dir();
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.filter_map(|e| e.ok())
|
||||
.collect();
|
||||
if file_folder.len() == 0 {
|
||||
return vec![];
|
||||
}
|
||||
file_folder
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for KeyWordItem {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("KeyWordItem")
|
||||
.field("value", &self.value)
|
||||
.field("path", &self.path)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct ConfigFile {
|
||||
pub keyword: Vec<KeyWordItem>,
|
||||
}
|
||||
|
||||
impl ConfigFile {
|
||||
pub fn parse_config(content: String) -> Result<ConfigFile, serde_yaml::Error> {
|
||||
let config: ConfigFile = serde_yaml::from_str(&content)?;
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConfigImgGlobal;
|
||||
|
||||
impl TypeMapKey for ConfigImgGlobal {
|
||||
type Value = ConfigFile;
|
||||
}
|
1
src/img/mod.rs
Normal file
1
src/img/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod config_file;
|
@ -1,2 +1,3 @@
|
||||
pub mod bot;
|
||||
pub mod config;
|
||||
pub mod bot;
|
||||
pub mod img;
|
||||
|
@ -1,5 +1,6 @@
|
||||
mod bot;
|
||||
mod config;
|
||||
mod img;
|
||||
|
||||
use actix_cors::Cors;
|
||||
use actix_web::{App, HttpServer};
|
||||
|
Loading…
Reference in New Issue
Block a user