Compare commits
10 Commits
1b2f0e25ac
...
a9f4240710
Author | SHA1 | Date | |
---|---|---|---|
a9f4240710 | |||
a709598cf6 | |||
52b9b6f968 | |||
8ae9ec821f | |||
0c1e534e19 | |||
f43bfe3a6a | |||
dcedac1128 | |||
0d0d744e33 | |||
4bf5646e28 | |||
48924d4bd9 |
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -3535,6 +3535,15 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_cow"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64e84ce5596a72f0c4c60759a10ff8c22d5eaf227b0dc2789c8746193309058b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.203"
|
||||
@ -3635,13 +3644,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serenity"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64da29158bb55d70677cacd4f4f8eab1acef005fb830d9c3bea411b090e96a9"
|
||||
version = "0.12.2"
|
||||
source = "git+https://github.com/serenity-rs/serenity?branch=current#060ee3281b44f7e532f3ea5863c5df57340e1ec9"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"async-trait",
|
||||
"base64 0.21.7",
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.5.0",
|
||||
"bytes",
|
||||
"chrono",
|
||||
@ -3655,6 +3663,7 @@ dependencies = [
|
||||
"reqwest",
|
||||
"secrecy",
|
||||
"serde",
|
||||
"serde_cow",
|
||||
"serde_json",
|
||||
"time",
|
||||
"tokio",
|
||||
|
@ -51,6 +51,8 @@ serde_with = "3.8.1"
|
||||
tokio-cron = "0.1.3"
|
||||
cron = "0.12.1"
|
||||
|
||||
[patch.crates-io]
|
||||
serenity = { git = "https://github.com/serenity-rs/serenity", branch = "current" }
|
||||
|
||||
[[bin]]
|
||||
name = "botdiscord"
|
||||
|
@ -10,7 +10,7 @@ Main lib used : [serenity-rs/serenity](https://github.com/serenity-rs/serenity)
|
||||
|
||||
- [DONE] ImageWareHouse (like TestDiscord)
|
||||
- ImageWareHouse V2
|
||||
- Mise en place d'autre source de gif OPT
|
||||
- Mise en place d'autre source de gif comme [Teno](https://developers.google.com/tenor/guides/quickstart?hl=fr)
|
||||
- SoundBoard (like UnlabeledBot)
|
||||
- Notification (read an event topic and send the message to the expected chan)
|
||||
- Some Administration command
|
||||
@ -24,9 +24,9 @@ Main lib used : [serenity-rs/serenity](https://github.com/serenity-rs/serenity)
|
||||
- Monitor the bot
|
||||
- Authentification Discord
|
||||
- Detecter controle
|
||||
- [WIP] Integrate with the Opentelemetry project
|
||||
- The bot has to be able to be deployed on a k8s cluster
|
||||
- The bot has to be OPT-IN (the user has to enable the bot on his server with a command)
|
||||
- [DONE] Integrate with the Opentelemetry project
|
||||
- [DONE] The bot has to be able to be deployed on a k8s cluster
|
||||
- [DONE] The bot has to be OPT-IN (the user has to enable the bot on his server with a command)
|
||||
- Mise en place de metric OpenTelemetry
|
||||
|
||||
## previous project
|
||||
|
@ -1,11 +1,14 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::botv2::{
|
||||
domain::concour::{
|
||||
check_if_allowed::check_if_allowed,
|
||||
set_periode::{set_periode, SetPeriodeConcourError},
|
||||
use crate::{
|
||||
botv2::{
|
||||
domain::concour::{
|
||||
check_if_allowed::check_if_allowed,
|
||||
set_periode::{set_periode, SetPeriodeConcourError},
|
||||
},
|
||||
init::{Context, Error},
|
||||
},
|
||||
init::{Context, Error},
|
||||
db::concour::ConcourStatus,
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use cron::Schedule;
|
||||
@ -66,7 +69,8 @@ pub async fn period(
|
||||
};
|
||||
let schedule = match Schedule::from_str(&cron_schedule) {
|
||||
Ok(schedule) => schedule,
|
||||
Err(_) => {
|
||||
Err(err) => {
|
||||
warn!(err = err.to_string(), "Cron format is invalid");
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Invalid CRON format")
|
||||
.color(colour::Color::RED)
|
||||
@ -118,16 +122,55 @@ pub async fn period(
|
||||
.color(colour::Color::RED)
|
||||
} else {
|
||||
let concour = concour.unwrap();
|
||||
CreateEmbed::new()
|
||||
let mut output = CreateEmbed::new()
|
||||
.title(concour.title)
|
||||
.description(concour.description)
|
||||
.field("Start date", concour.start_date.to_string(), false)
|
||||
.field("Periode", concour.periode.to_string(), false)
|
||||
.field(
|
||||
.field("Periode", concour.periode.to_string(), false);
|
||||
|
||||
if concour.role_recompense == 0 {
|
||||
output = output.field("Role récompense", "Aucun", false);
|
||||
} else {
|
||||
output = output.field(
|
||||
"Role récompense",
|
||||
RoleId::new(concour.role_recompense).mention().to_string(),
|
||||
false,
|
||||
)
|
||||
);
|
||||
}
|
||||
// Restart the cronjob if concour is ongoing
|
||||
if concour.status == ConcourStatus::OnGoing {
|
||||
{
|
||||
let mut scheduler = ctx.data().scheduler.clone();
|
||||
match scheduler
|
||||
.stop_scheduled_job(concour.server_id, concour.channel_id)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
info!("Cronjob stopped");
|
||||
match scheduler
|
||||
.add_concour_cron_job(
|
||||
concour.server_id,
|
||||
concour.channel_id,
|
||||
concour.periode,
|
||||
ctx.http(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
info!("Cronjob restarted");
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Error restarting cronjob");
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(err = err.to_string(), "Error stopping cronjob");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
Err(err) => match err {
|
||||
|
@ -83,6 +83,11 @@ pub async fn start(ctx: Context<'_>) -> Result<(), Error> {
|
||||
Some(role) => RoleId::new(role).mention().to_string(),
|
||||
None => "".to_string(),
|
||||
};
|
||||
let role_recompense = if concour.role_recompense != 0 {
|
||||
RoleId::new(concour.role_recompense).mention().to_string()
|
||||
} else {
|
||||
"(Pas encore définis)".to_string()
|
||||
};
|
||||
let text = format!("
|
||||
Bonsoir !
|
||||
|
||||
@ -90,14 +95,14 @@ Bonsoir !
|
||||
|
||||
📜 ❱ Les règles : Pas de loli, ni de shoota, ni de irl, ni de zoo.
|
||||
|
||||
Celui ou celle qui a le plus de votes gagne, comme récompense elle aura le rôle @ROLE pour une durée de 48h.
|
||||
Celui ou celle qui a le plus de votes gagne, comme récompense elle aura le rôle {} pour une durée de 48h.
|
||||
Le concours ce termine dans deux jours.
|
||||
Ceux qui votent pour leur propre photo, cela ne sera pas pris en compte, une photo par personne.
|
||||
|
||||
À vos photos !
|
||||
|
||||
{}
|
||||
", keyword.to_string(),ping_concour);
|
||||
", keyword,role_recompense,ping_concour);
|
||||
let output = CreateEmbed::new()
|
||||
.title(format!(
|
||||
"Concour: {} Jour : {}",
|
||||
|
18
src/botv2/cmd/meme/main.rs
Normal file
18
src/botv2/cmd/meme/main.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use crate::botv2::{
|
||||
cmd::meme::{answer::answer, enable::enable, list::list},
|
||||
init::{Context, Error},
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
/// Handle meme command
|
||||
#[instrument(skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))]
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
prefix_command,
|
||||
category = "mem",
|
||||
subcommands("answer", "enable", "list"),
|
||||
guild_only = true
|
||||
)]
|
||||
pub async fn meme(ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod answer;
|
||||
pub mod enable;
|
||||
pub mod list;
|
||||
pub mod main;
|
||||
|
@ -1,121 +1,18 @@
|
||||
use super::init::{Data, Error};
|
||||
use crate::{db::user_image::User, img::config_file::KeyWordItem};
|
||||
use poise::serenity_prelude as serenity;
|
||||
use rand::Rng;
|
||||
use serenity::all::{CreateAttachment, CreateMessage};
|
||||
use tokio::fs::File;
|
||||
use tracing::{info, instrument};
|
||||
|
||||
#[instrument(skip(ctx, _framework, data), err, level = "trace")]
|
||||
#[allow(clippy::single_match)]
|
||||
#[instrument(skip(_ctx, _framework, _data), err, level = "trace")]
|
||||
pub async fn event_handler(
|
||||
ctx: &serenity::Context,
|
||||
_ctx: &serenity::Context,
|
||||
event: &serenity::FullEvent,
|
||||
_framework: poise::FrameworkContext<'_, Data, Error>,
|
||||
data: &Data,
|
||||
_data: &Data,
|
||||
) -> Result<(), Error> {
|
||||
match event {
|
||||
serenity::FullEvent::Ready { data_about_bot, .. } => {
|
||||
info!("{} is connected !", data_about_bot.user.name);
|
||||
}
|
||||
serenity::FullEvent::Message { new_message } => {
|
||||
if new_message.author.bot
|
||||
|| new_message.content.starts_with(&data.config.prefix.clone())
|
||||
|| new_message.content.is_empty()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
let config_img = data.config_img.clone();
|
||||
let config = data.config.clone();
|
||||
let guild = match new_message.guild_id {
|
||||
Some(guild) => guild,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let user_in_db =
|
||||
match User::find_by_server_id_user_id(&guild.get(), &new_message.author.id.get())
|
||||
.await
|
||||
{
|
||||
Ok(Some(user_in_db)) => user_in_db.clone(),
|
||||
Ok(None) => {
|
||||
let user_in_db =
|
||||
User::new(guild.get(), new_message.author.id.get(), false).unwrap();
|
||||
match user_in_db.create().await {
|
||||
Ok(_) => user_in_db,
|
||||
Err(e) => {
|
||||
println!("Error saving user image: {:?}", e);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error finding user image: {:?}", e);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
if !user_in_db.enable {
|
||||
return Ok(());
|
||||
}
|
||||
if config_img.keyword.is_empty() || new_message.content.len() > 50 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let folder_container = match config_img
|
||||
.keyword
|
||||
.iter()
|
||||
.find(|keyword| keyword.does_value_match(new_message.content.clone()))
|
||||
{
|
||||
Some(keyword_matching) => {
|
||||
println!("{} match {:?}", new_message.content, keyword_matching);
|
||||
let keyword_path = match keyword_matching.path.len() {
|
||||
0 => keyword_matching.path[0].clone(),
|
||||
_ => {
|
||||
let id: usize = {
|
||||
let mut rng = rand::thread_rng();
|
||||
rng.gen_range(0..keyword_matching.path.len())
|
||||
};
|
||||
keyword_matching.path[id].clone()
|
||||
}
|
||||
};
|
||||
|
||||
keyword_path.clone()
|
||||
}
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let path = format!("{}/{}", config.image.path.clone(), folder_container);
|
||||
let file_folder = KeyWordItem::output_folder_content(path.clone());
|
||||
let id_rand: usize = {
|
||||
let mut rng = rand::thread_rng();
|
||||
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 Ok(()),
|
||||
};
|
||||
let file_path = format!("{}/{}", path, filename);
|
||||
let file = match File::open(file_path).await {
|
||||
Ok(file) => file,
|
||||
Err(why) => {
|
||||
println!("Error opening file: {:?}", why);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let attachment = match CreateAttachment::file(&file, filename).await {
|
||||
Ok(attachment) => attachment,
|
||||
Err(why) => {
|
||||
println!("Error creating attachment: {:?}", why);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let builder = CreateMessage::new().add_file(attachment);
|
||||
|
||||
if let Err(why) = new_message
|
||||
.channel_id
|
||||
.send_message(&ctx.http, builder)
|
||||
.await
|
||||
{
|
||||
println!("Error sending message: {:?}", why);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::botv2::cmd::meme::{answer::answer, enable::enable, list::list};
|
||||
use crate::botv2::cmd::meme::main::meme;
|
||||
use crate::botv2::cmd::server_config::server::server;
|
||||
use crate::botv2::cmd::{help::help, ping::ping};
|
||||
use crate::config::Config;
|
||||
@ -9,7 +9,7 @@ use serenity::GatewayIntents;
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::oneshot;
|
||||
use tracing::{info, instrument};
|
||||
use tracing::info;
|
||||
|
||||
use super::cmd::concour::main::concour;
|
||||
|
||||
@ -24,18 +24,6 @@ pub struct Data {
|
||||
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||
pub type Context<'a> = poise::Context<'a, Data, Error>;
|
||||
|
||||
#[instrument(skip(ctx), level = "info")]
|
||||
#[poise::command(slash_command, prefix_command)]
|
||||
async fn age(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Selected user"] user: Option<serenity::User>,
|
||||
) -> Result<(), Error> {
|
||||
let u = user.as_ref().unwrap_or_else(|| ctx.author());
|
||||
let response = format!("{}'s account was created at {}", u.name, u.created_at());
|
||||
ctx.say(response).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn start_bot(
|
||||
config: Config,
|
||||
rx: oneshot::Receiver<()>,
|
||||
@ -67,16 +55,7 @@ pub async fn start_bot(
|
||||
let prefix = config.prefix.clone();
|
||||
let framework = poise::Framework::builder()
|
||||
.options(poise::FrameworkOptions {
|
||||
commands: vec![
|
||||
age(),
|
||||
ping(),
|
||||
help(),
|
||||
list(),
|
||||
enable(),
|
||||
answer(),
|
||||
server(),
|
||||
concour(),
|
||||
],
|
||||
commands: vec![ping(), help(), meme(), server(), concour()],
|
||||
prefix_options: poise::PrefixFrameworkOptions {
|
||||
prefix: Some(prefix),
|
||||
..Default::default()
|
||||
|
@ -1,5 +1,5 @@
|
||||
use poise::serenity_prelude::{
|
||||
Color, CreateEmbed, CreateMessage, Http, Mentionable, MessagePagination,
|
||||
Color, CreateEmbed, CreateMessage, Http, Mentionable, MessagePagination, RoleId,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -291,16 +291,16 @@ impl ScheduleJob {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let embed = CreateEmbed::default()
|
||||
.title("Winner")
|
||||
.description(format!("The winner is {}", winner.mention()))
|
||||
.color(Color::DARK_GREEN);
|
||||
let reply = CreateMessage::default().embed(embed);
|
||||
if let Err(err) =
|
||||
http.send_message(channel_id.into(), vec![], &reply).await
|
||||
{
|
||||
error!("Error sending message: {:?}", err);
|
||||
}
|
||||
// let embed = CreateEmbed::default()
|
||||
// .title("Winner")
|
||||
// .description(format!("The winner is {}", winner.mention()))
|
||||
// .color(Color::DARK_GREEN);
|
||||
// let reply = CreateMessage::default().embed(embed);
|
||||
// if let Err(err) =
|
||||
// http.send_message(channel_id.into(), vec![], &reply).await
|
||||
// {
|
||||
// error!("Error sending message: {:?}", err);
|
||||
// }
|
||||
let (add, previous) = match concour.winner.last() {
|
||||
Some(previous_winner) => (
|
||||
previous_winner.user_id != winner.id.get(),
|
||||
@ -376,6 +376,33 @@ impl ScheduleJob {
|
||||
.keywords
|
||||
.get(concour.index_keyword as usize)
|
||||
.unwrap();
|
||||
let ping_role = match concour.ping_concour {
|
||||
Some(role_id) => RoleId::new(role_id).mention().to_string(),
|
||||
None => "".to_string(),
|
||||
};
|
||||
let role_recompense = if concour.role_recompense != 0 {
|
||||
RoleId::new(concour.role_recompense).mention().to_string()
|
||||
} else {
|
||||
"(Pas encore définis)".to_string()
|
||||
};
|
||||
let answer = format!(
|
||||
"Bonsoir !
|
||||
|
||||
🏆 ❱ Bravo à {} pour ses réactions sous son image.
|
||||
|
||||
👹 ❱ Le thème de ce soir est : {}
|
||||
|
||||
📜 ❱ Les règles : Pas de loli, ni de shoota, ni de irl, ni de zoo.
|
||||
|
||||
Celui ou celle qui a le plus de votes gagne, comme récompense elle aura le rôle {} pour une durée de 48h.
|
||||
Le concours ce termine dans deux jours.
|
||||
Ceux qui votent pour leur propre photo, cela ne sera pas pris en compte, une photo par personne.
|
||||
|
||||
À vos photos !
|
||||
|
||||
{}",
|
||||
winner.id.mention(), next_keyword,role_recompense, ping_role
|
||||
);
|
||||
let output = CreateEmbed::new()
|
||||
.title(format!(
|
||||
"Concour: {} Jour : {}",
|
||||
@ -391,7 +418,12 @@ impl ScheduleJob {
|
||||
false,
|
||||
)
|
||||
.color(Color::DARK_GREEN);
|
||||
let reply = CreateMessage::default().embed(output);
|
||||
let mut reply = CreateMessage::default();
|
||||
if !answer.is_empty() {
|
||||
reply = reply.content(answer);
|
||||
}else{
|
||||
reply = reply.embed(output);
|
||||
}
|
||||
let last_id =
|
||||
match http.send_message(channel_id.into(), vec![], &reply).await {
|
||||
Ok(message) => message.id,
|
||||
|
Loading…
Reference in New Issue
Block a user