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",
|
"dotenvy",
|
||||||
"openssl",
|
"openssl",
|
||||||
"postgres-openssl",
|
"postgres-openssl",
|
||||||
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_yaml",
|
||||||
"serenity",
|
"serenity",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -391,6 +393,7 @@ dependencies = [
|
|||||||
"utoipa",
|
"utoipa",
|
||||||
"utoipa-swagger-ui",
|
"utoipa-swagger-ui",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1856,6 +1859,19 @@ dependencies = [
|
|||||||
"serde",
|
"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]]
|
[[package]]
|
||||||
name = "serenity"
|
name = "serenity"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
@ -2392,6 +2408,12 @@ dependencies = [
|
|||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unsafe-libyaml"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -8,6 +8,7 @@ default-run = "botdiscord"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
serde_yaml = "0.9"
|
||||||
uuid = { version = "1.4", features = ["v4", "serde"] }
|
uuid = { version = "1.4", features = ["v4", "serde"] }
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] }
|
utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] }
|
||||||
@ -40,6 +41,8 @@ serenity = { version = "0.12", default-features = false, features = [
|
|||||||
"cache",
|
"cache",
|
||||||
] }
|
] }
|
||||||
tokio = { version = "1.35", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.35", features = ["macros", "rt-multi-thread"] }
|
||||||
|
rand = "0.8.5"
|
||||||
|
walkdir = "2.4.0"
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
|
use rand::Rng;
|
||||||
|
use serenity::prelude::*;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
all::{Message, Ready},
|
all::{Message, Ready},
|
||||||
async_trait,
|
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;
|
pub struct Handler;
|
||||||
@ -9,7 +19,7 @@ pub struct Handler;
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn message(&self, ctx: Context, msg: Message) {
|
async fn message(&self, ctx: Context, msg: Message) {
|
||||||
if msg.author.bot {
|
if msg.author.bot || msg.content.starts_with("!") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if msg.content == "&ping" {
|
if msg.content == "&ping" {
|
||||||
@ -18,6 +28,64 @@ impl EventHandler for Handler {
|
|||||||
}
|
}
|
||||||
return;
|
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) {
|
async fn ready(&self, _: Context, ready: Ready) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::cmd::{help::HELP, ping::PING_COMMAND};
|
use super::cmd::{help::HELP, ping::PING_COMMAND};
|
||||||
use super::handler::Handler;
|
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::framework::standard::Configuration;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
all::GatewayIntents,
|
all::GatewayIntents,
|
||||||
@ -9,6 +10,7 @@ use serenity::{
|
|||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::fs;
|
||||||
use tokio::task::spawn_blocking;
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
#[group]
|
#[group]
|
||||||
@ -23,6 +25,23 @@ pub fn start_bot(config: Config) {
|
|||||||
let local = tokio::task::LocalSet::new();
|
let local = tokio::task::LocalSet::new();
|
||||||
let _ = local
|
let _ = local
|
||||||
.run_until(async move {
|
.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
|
let intents = GatewayIntents::GUILD_MESSAGES
|
||||||
| GatewayIntents::DIRECT_MESSAGES
|
| GatewayIntents::DIRECT_MESSAGES
|
||||||
| GatewayIntents::MESSAGE_CONTENT
|
| GatewayIntents::MESSAGE_CONTENT
|
||||||
@ -53,7 +72,7 @@ pub fn start_bot(config: Config) {
|
|||||||
framework.configure(
|
framework.configure(
|
||||||
Configuration::new()
|
Configuration::new()
|
||||||
.with_whitespace(true)
|
.with_whitespace(true)
|
||||||
.prefix(config.prefix)
|
.prefix(config.prefix.clone())
|
||||||
.owners(owners),
|
.owners(owners),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -62,6 +81,14 @@ pub fn start_bot(config: Config) {
|
|||||||
.framework(framework)
|
.framework(framework)
|
||||||
.await
|
.await
|
||||||
.expect("Err creating client");
|
.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 {
|
if let Err(why) = client.start().await {
|
||||||
println!("Client error: {why:?}");
|
println!("Client error: {why:?}");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use serenity::prelude::TypeMapKey;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -22,6 +23,12 @@ const RUST_ENV: &str = "RUST_ENV";
|
|||||||
|
|
||||||
const PORT: &str = "PORT";
|
const PORT: &str = "PORT";
|
||||||
|
|
||||||
|
pub struct ConfigGlobal;
|
||||||
|
|
||||||
|
impl TypeMapKey for ConfigGlobal {
|
||||||
|
type Value = Config;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub bot_name: String,
|
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 config;
|
||||||
pub mod bot;
|
pub mod img;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
mod bot;
|
mod bot;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod img;
|
||||||
|
|
||||||
use actix_cors::Cors;
|
use actix_cors::Cors;
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
Loading…
Reference in New Issue
Block a user