178 lines
6.4 KiB
Rust
178 lines
6.4 KiB
Rust
use crate::helper::is_user_admin_right;
|
|
use crate::{Context, Error};
|
|
use clickhouse_pool::traits::Model;
|
|
use croner::Cron;
|
|
use database::trivial::{Trivial, TrivialRewardKind};
|
|
use poise::serenity_prelude::{Channel, Role};
|
|
use tracing::{debug, info, instrument};
|
|
|
|
/// Config an existing trivia game
|
|
#[instrument(name="trivia_config", skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))]
|
|
#[poise::command(
|
|
prefix_command,
|
|
slash_command,
|
|
guild_only,
|
|
category = "Trivia",
|
|
check = "is_user_admin_right"
|
|
)]
|
|
pub async fn config(
|
|
ctx: Context<'_>,
|
|
#[description = "Channel of the trivia game, or current"] channel_id: Option<Channel>,
|
|
#[description = "Name of the trivia game"] name: Option<String>,
|
|
#[description = "Description of the trivia game"] description: Option<String>,
|
|
#[description = "Whether to use random questions"] random_question: Option<bool>,
|
|
#[description = "Role to ping when a question is asked"] role_ping: Option<Role>,
|
|
#[description = "Whether to enable role ping"] role_ping_enabled: Option<bool>,
|
|
#[description = "Reward kind for the trivia game"] reward_kind: Option<TrivialRewardKind>,
|
|
#[description = "Reward amount for the trivia game"] reward_amount: Option<u64>,
|
|
#[description = "Whether to send an ephemeral message when the answer is taken into account"]
|
|
taken_into_account: Option<bool>,
|
|
#[description = "When to ask the question, in cron format (e.g. '0 0 * * *' for daily)"]
|
|
cron: Option<String>,
|
|
#[description = "When to answer the question, in cron format (e.g. '0 0 * * *' for daily)"]
|
|
cron_answer: Option<String>,
|
|
) -> Result<(), Error> {
|
|
let guild_id = match ctx.guild_id() {
|
|
Some(id) => id.get(),
|
|
None => {
|
|
ctx.say("This command can only be used in a server.")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
};
|
|
let channel_id = match channel_id {
|
|
Some(c) => c.id().get(),
|
|
None => {
|
|
info!("No channel specified, using current channel.");
|
|
ctx.channel_id().get()
|
|
}
|
|
};
|
|
let manager = ctx.data().datalake_config.clone();
|
|
let search_query = Trivial::build_select_query(
|
|
Some(&format!(
|
|
"channel_id = {} and guild_id = {}",
|
|
channel_id, guild_id
|
|
)),
|
|
None,
|
|
None,
|
|
);
|
|
let mut trivia_exists: Trivial = match manager
|
|
.execute_select_with_retry::<Trivial>(&search_query)
|
|
.await
|
|
{
|
|
Ok(trivia) => {
|
|
if trivia.is_empty() {
|
|
ctx.say("No trivia game found in this channel. Please create one first.")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
if trivia.len() > 1 {
|
|
ctx.say("Multiple trivia games found in this channel. Please contact an admin to resolve this.")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
trivia[0].clone()
|
|
}
|
|
Err(e) => {
|
|
ctx.say(format!("Error fetching trivia game: {}", e))
|
|
.await?;
|
|
return Err(Error::from(e));
|
|
}
|
|
};
|
|
debug!("Found trivia game: {:?}", trivia_exists);
|
|
let mut inserter = match manager.get_insert::<Trivial>(Trivial::table_name()).await {
|
|
Ok(inserter) => inserter,
|
|
Err(e) => {
|
|
tracing::error!("Failed to create inserter for Trivial: {}", e);
|
|
ctx.say("Failed to update trivia game. Please try again later.")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
};
|
|
trivia_exists.sign = -1; // Set sign to -1 to indicate an update
|
|
inserter.write(&trivia_exists.clone()).await?;
|
|
// Update the trivia game with provided options
|
|
if let Some(name) = name {
|
|
trivia_exists.name = name;
|
|
}
|
|
if let Some(description) = description {
|
|
trivia_exists.description = description;
|
|
}
|
|
if let Some(random_question) = random_question {
|
|
trivia_exists.random_question = random_question;
|
|
}
|
|
if let Some(role_ping) = role_ping {
|
|
trivia_exists.role_ping = role_ping.id.get();
|
|
}
|
|
if let Some(role_ping_enabled) = role_ping_enabled {
|
|
trivia_exists.role_ping_enabled = role_ping_enabled;
|
|
}
|
|
if let Some(reward_kind) = reward_kind {
|
|
trivia_exists.reward_kind = reward_kind;
|
|
}
|
|
if let Some(reward_amount) = reward_amount {
|
|
trivia_exists.reward_amount = reward_amount;
|
|
}
|
|
if let Some(taken_into_account) = taken_into_account {
|
|
trivia_exists.taken_into_account = taken_into_account;
|
|
}
|
|
if let Some(cron) = cron {
|
|
match Cron::new(&cron).parse() {
|
|
Ok(_) => {}
|
|
Err(e) => {
|
|
ctx.say(format!("Invalid cron format: {}", e)).await?;
|
|
return Ok(());
|
|
}
|
|
};
|
|
trivia_exists.question_asked = cron;
|
|
}
|
|
if let Some(cron_answer) = cron_answer {
|
|
match Cron::new(&cron_answer).parse() {
|
|
Ok(_) => {}
|
|
Err(e) => {
|
|
ctx.say(format!("Invalid cron answer format: {}", e))
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
};
|
|
trivia_exists.answer_given = cron_answer;
|
|
}
|
|
trivia_exists.updated_at = chrono::Utc::now();
|
|
trivia_exists.updater_id = ctx.author().id.get();
|
|
debug!("Updated trivia game: {:?}", trivia_exists);
|
|
// Set sign to 1 to indicate a successful update
|
|
trivia_exists.sign = 1;
|
|
// Write the updated trivia game back to the database
|
|
inserter.write(&trivia_exists).await?;
|
|
match inserter.end().await {
|
|
Ok(_) => {
|
|
info!(
|
|
"Trivia game '{}' updated successfully in channel <#{}>.",
|
|
trivia_exists.name, channel_id
|
|
);
|
|
ctx.say(format!(
|
|
"Trivia game '{}' has been successfully updated.",
|
|
trivia_exists.name
|
|
))
|
|
.await?;
|
|
}
|
|
Err(e) => {
|
|
tracing::error!("Failed to update trivia game: {}", e);
|
|
ctx.say("Failed to update trivia game. Please try again later.")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
if let Err(e) = manager
|
|
.execute_with_retry(&Trivial::optimize_table_sql())
|
|
.await
|
|
{
|
|
tracing::error!("Failed to optimize trivia table: {}", e);
|
|
} else {
|
|
info!("Trivia table optimized successfully.");
|
|
}
|
|
|
|
Ok(())
|
|
}
|