Compare commits
No commits in common. "a9f4240710049a96917674b57c1b7bf3ff459a0b" and "1b2f0e25acef7928e33564ed8e6a146a88863227" have entirely different histories.
a9f4240710
...
1b2f0e25ac
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -3535,15 +3535,6 @@ dependencies = [
|
|||||||
"serde_derive",
|
"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]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.203"
|
version = "1.0.203"
|
||||||
@ -3644,12 +3635,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serenity"
|
name = "serenity"
|
||||||
version = "0.12.2"
|
version = "0.12.1"
|
||||||
source = "git+https://github.com/serenity-rs/serenity?branch=current#060ee3281b44f7e532f3ea5863c5df57340e1ec9"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c64da29158bb55d70677cacd4f4f8eab1acef005fb830d9c3bea411b090e96a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.22.1",
|
"base64 0.21.7",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -3663,7 +3655,6 @@ dependencies = [
|
|||||||
"reqwest",
|
"reqwest",
|
||||||
"secrecy",
|
"secrecy",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_cow",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -51,8 +51,6 @@ serde_with = "3.8.1"
|
|||||||
tokio-cron = "0.1.3"
|
tokio-cron = "0.1.3"
|
||||||
cron = "0.12.1"
|
cron = "0.12.1"
|
||||||
|
|
||||||
[patch.crates-io]
|
|
||||||
serenity = { git = "https://github.com/serenity-rs/serenity", branch = "current" }
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "botdiscord"
|
name = "botdiscord"
|
||||||
|
@ -10,7 +10,7 @@ Main lib used : [serenity-rs/serenity](https://github.com/serenity-rs/serenity)
|
|||||||
|
|
||||||
- [DONE] ImageWareHouse (like TestDiscord)
|
- [DONE] ImageWareHouse (like TestDiscord)
|
||||||
- ImageWareHouse V2
|
- ImageWareHouse V2
|
||||||
- Mise en place d'autre source de gif comme [Teno](https://developers.google.com/tenor/guides/quickstart?hl=fr)
|
- Mise en place d'autre source de gif OPT
|
||||||
- SoundBoard (like UnlabeledBot)
|
- SoundBoard (like UnlabeledBot)
|
||||||
- Notification (read an event topic and send the message to the expected chan)
|
- Notification (read an event topic and send the message to the expected chan)
|
||||||
- Some Administration command
|
- Some Administration command
|
||||||
@ -24,9 +24,9 @@ Main lib used : [serenity-rs/serenity](https://github.com/serenity-rs/serenity)
|
|||||||
- Monitor the bot
|
- Monitor the bot
|
||||||
- Authentification Discord
|
- Authentification Discord
|
||||||
- Detecter controle
|
- Detecter controle
|
||||||
- [DONE] Integrate with the Opentelemetry project
|
- [WIP] Integrate with the Opentelemetry project
|
||||||
- [DONE] The bot has to be able to be deployed on a k8s cluster
|
- 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)
|
- 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
|
- Mise en place de metric OpenTelemetry
|
||||||
|
|
||||||
## previous project
|
## previous project
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::botv2::{
|
||||||
botv2::{
|
|
||||||
domain::concour::{
|
domain::concour::{
|
||||||
check_if_allowed::check_if_allowed,
|
check_if_allowed::check_if_allowed,
|
||||||
set_periode::{set_periode, SetPeriodeConcourError},
|
set_periode::{set_periode, SetPeriodeConcourError},
|
||||||
},
|
},
|
||||||
init::{Context, Error},
|
init::{Context, Error},
|
||||||
},
|
|
||||||
db::concour::ConcourStatus,
|
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use cron::Schedule;
|
use cron::Schedule;
|
||||||
@ -69,8 +66,7 @@ pub async fn period(
|
|||||||
};
|
};
|
||||||
let schedule = match Schedule::from_str(&cron_schedule) {
|
let schedule = match Schedule::from_str(&cron_schedule) {
|
||||||
Ok(schedule) => schedule,
|
Ok(schedule) => schedule,
|
||||||
Err(err) => {
|
Err(_) => {
|
||||||
warn!(err = err.to_string(), "Cron format is invalid");
|
|
||||||
let embed = CreateEmbed::new()
|
let embed = CreateEmbed::new()
|
||||||
.title("Invalid CRON format")
|
.title("Invalid CRON format")
|
||||||
.color(colour::Color::RED)
|
.color(colour::Color::RED)
|
||||||
@ -122,55 +118,16 @@ pub async fn period(
|
|||||||
.color(colour::Color::RED)
|
.color(colour::Color::RED)
|
||||||
} else {
|
} else {
|
||||||
let concour = concour.unwrap();
|
let concour = concour.unwrap();
|
||||||
let mut output = CreateEmbed::new()
|
CreateEmbed::new()
|
||||||
.title(concour.title)
|
.title(concour.title)
|
||||||
.description(concour.description)
|
.description(concour.description)
|
||||||
.field("Start date", concour.start_date.to_string(), false)
|
.field("Start date", concour.start_date.to_string(), false)
|
||||||
.field("Periode", concour.periode.to_string(), false);
|
.field("Periode", concour.periode.to_string(), false)
|
||||||
|
.field(
|
||||||
if concour.role_recompense == 0 {
|
|
||||||
output = output.field("Role récompense", "Aucun", false);
|
|
||||||
} else {
|
|
||||||
output = output.field(
|
|
||||||
"Role récompense",
|
"Role récompense",
|
||||||
RoleId::new(concour.role_recompense).mention().to_string(),
|
RoleId::new(concour.role_recompense).mention().to_string(),
|
||||||
false,
|
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 {
|
Err(err) => match err {
|
||||||
|
@ -83,11 +83,6 @@ pub async fn start(ctx: Context<'_>) -> Result<(), Error> {
|
|||||||
Some(role) => RoleId::new(role).mention().to_string(),
|
Some(role) => RoleId::new(role).mention().to_string(),
|
||||||
None => "".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!("
|
let text = format!("
|
||||||
Bonsoir !
|
Bonsoir !
|
||||||
|
|
||||||
@ -95,14 +90,14 @@ Bonsoir !
|
|||||||
|
|
||||||
📜 ❱ Les règles : Pas de loli, ni de shoota, ni de irl, ni de zoo.
|
📜 ❱ 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.
|
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.
|
||||||
Le concours ce termine dans deux jours.
|
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.
|
Ceux qui votent pour leur propre photo, cela ne sera pas pris en compte, une photo par personne.
|
||||||
|
|
||||||
À vos photos !
|
À vos photos !
|
||||||
|
|
||||||
{}
|
{}
|
||||||
", keyword,role_recompense,ping_concour);
|
", keyword.to_string(),ping_concour);
|
||||||
let output = CreateEmbed::new()
|
let output = CreateEmbed::new()
|
||||||
.title(format!(
|
.title(format!(
|
||||||
"Concour: {} Jour : {}",
|
"Concour: {} Jour : {}",
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
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,4 +1,3 @@
|
|||||||
pub mod answer;
|
pub mod answer;
|
||||||
pub mod enable;
|
pub mod enable;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod main;
|
|
||||||
|
@ -1,18 +1,121 @@
|
|||||||
use super::init::{Data, Error};
|
use super::init::{Data, Error};
|
||||||
|
use crate::{db::user_image::User, img::config_file::KeyWordItem};
|
||||||
use poise::serenity_prelude as serenity;
|
use poise::serenity_prelude as serenity;
|
||||||
|
use rand::Rng;
|
||||||
|
use serenity::all::{CreateAttachment, CreateMessage};
|
||||||
|
use tokio::fs::File;
|
||||||
use tracing::{info, instrument};
|
use tracing::{info, instrument};
|
||||||
#[allow(clippy::single_match)]
|
|
||||||
#[instrument(skip(_ctx, _framework, _data), err, level = "trace")]
|
#[instrument(skip(ctx, _framework, data), err, level = "trace")]
|
||||||
pub async fn event_handler(
|
pub async fn event_handler(
|
||||||
_ctx: &serenity::Context,
|
ctx: &serenity::Context,
|
||||||
event: &serenity::FullEvent,
|
event: &serenity::FullEvent,
|
||||||
_framework: poise::FrameworkContext<'_, Data, Error>,
|
_framework: poise::FrameworkContext<'_, Data, Error>,
|
||||||
_data: &Data,
|
data: &Data,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match event {
|
match event {
|
||||||
serenity::FullEvent::Ready { data_about_bot, .. } => {
|
serenity::FullEvent::Ready { data_about_bot, .. } => {
|
||||||
info!("{} is connected !", data_about_bot.user.name);
|
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(())
|
Ok(())
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::botv2::cmd::meme::main::meme;
|
use crate::botv2::cmd::meme::{answer::answer, enable::enable, list::list};
|
||||||
use crate::botv2::cmd::server_config::server::server;
|
use crate::botv2::cmd::server_config::server::server;
|
||||||
use crate::botv2::cmd::{help::help, ping::ping};
|
use crate::botv2::cmd::{help::help, ping::ping};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@ -9,7 +9,7 @@ use serenity::GatewayIntents;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
use tracing::info;
|
use tracing::{info, instrument};
|
||||||
|
|
||||||
use super::cmd::concour::main::concour;
|
use super::cmd::concour::main::concour;
|
||||||
|
|
||||||
@ -24,6 +24,18 @@ pub struct Data {
|
|||||||
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||||
pub type Context<'a> = poise::Context<'a, Data, Error>;
|
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(
|
pub async fn start_bot(
|
||||||
config: Config,
|
config: Config,
|
||||||
rx: oneshot::Receiver<()>,
|
rx: oneshot::Receiver<()>,
|
||||||
@ -55,7 +67,16 @@ pub async fn start_bot(
|
|||||||
let prefix = config.prefix.clone();
|
let prefix = config.prefix.clone();
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
commands: vec![ping(), help(), meme(), server(), concour()],
|
commands: vec![
|
||||||
|
age(),
|
||||||
|
ping(),
|
||||||
|
help(),
|
||||||
|
list(),
|
||||||
|
enable(),
|
||||||
|
answer(),
|
||||||
|
server(),
|
||||||
|
concour(),
|
||||||
|
],
|
||||||
prefix_options: poise::PrefixFrameworkOptions {
|
prefix_options: poise::PrefixFrameworkOptions {
|
||||||
prefix: Some(prefix),
|
prefix: Some(prefix),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use poise::serenity_prelude::{
|
use poise::serenity_prelude::{
|
||||||
Color, CreateEmbed, CreateMessage, Http, Mentionable, MessagePagination, RoleId,
|
Color, CreateEmbed, CreateMessage, Http, Mentionable, MessagePagination,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@ -291,16 +291,16 @@ impl ScheduleJob {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// let embed = CreateEmbed::default()
|
let embed = CreateEmbed::default()
|
||||||
// .title("Winner")
|
.title("Winner")
|
||||||
// .description(format!("The winner is {}", winner.mention()))
|
.description(format!("The winner is {}", winner.mention()))
|
||||||
// .color(Color::DARK_GREEN);
|
.color(Color::DARK_GREEN);
|
||||||
// let reply = CreateMessage::default().embed(embed);
|
let reply = CreateMessage::default().embed(embed);
|
||||||
// if let Err(err) =
|
if let Err(err) =
|
||||||
// http.send_message(channel_id.into(), vec![], &reply).await
|
http.send_message(channel_id.into(), vec![], &reply).await
|
||||||
// {
|
{
|
||||||
// error!("Error sending message: {:?}", err);
|
error!("Error sending message: {:?}", err);
|
||||||
// }
|
}
|
||||||
let (add, previous) = match concour.winner.last() {
|
let (add, previous) = match concour.winner.last() {
|
||||||
Some(previous_winner) => (
|
Some(previous_winner) => (
|
||||||
previous_winner.user_id != winner.id.get(),
|
previous_winner.user_id != winner.id.get(),
|
||||||
@ -376,33 +376,6 @@ impl ScheduleJob {
|
|||||||
.keywords
|
.keywords
|
||||||
.get(concour.index_keyword as usize)
|
.get(concour.index_keyword as usize)
|
||||||
.unwrap();
|
.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()
|
let output = CreateEmbed::new()
|
||||||
.title(format!(
|
.title(format!(
|
||||||
"Concour: {} Jour : {}",
|
"Concour: {} Jour : {}",
|
||||||
@ -418,12 +391,7 @@ Ceux qui votent pour leur propre photo, cela ne sera pas pris en compte, une pho
|
|||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.color(Color::DARK_GREEN);
|
.color(Color::DARK_GREEN);
|
||||||
let mut reply = CreateMessage::default();
|
let reply = CreateMessage::default().embed(output);
|
||||||
if !answer.is_empty() {
|
|
||||||
reply = reply.content(answer);
|
|
||||||
}else{
|
|
||||||
reply = reply.embed(output);
|
|
||||||
}
|
|
||||||
let last_id =
|
let last_id =
|
||||||
match http.send_message(channel_id.into(), vec![], &reply).await {
|
match http.send_message(channel_id.into(), vec![], &reply).await {
|
||||||
Ok(message) => message.id,
|
Ok(message) => message.id,
|
||||||
|
Loading…
Reference in New Issue
Block a user