feat: Added publish command
- /quest update also updates quest message if published
This commit is contained in:
parent
ced69e494f
commit
85e8070daa
1 changed files with 115 additions and 2 deletions
|
|
@ -1,13 +1,26 @@
|
||||||
use std::str::FromStr;
|
use std::{future, path::Path, str::FromStr};
|
||||||
|
|
||||||
|
use poise::serenity_prelude::{CreateMessage, EditMessage, Mentionable, futures::StreamExt};
|
||||||
use squad_quest::{SquadObject, quest::{Quest, QuestDifficulty}};
|
use squad_quest::{SquadObject, quest::{Quest, QuestDifficulty}};
|
||||||
use toml::value::Date;
|
use toml::value::Date;
|
||||||
use crate::{Context, Error, commands::ERROR_MSG};
|
use crate::{Context, Error, commands::ERROR_MSG};
|
||||||
|
|
||||||
|
fn make_quest_message_content(quest: &Quest) -> String {
|
||||||
|
format!("### `#{id}` {name} (+{reward})\n\
|
||||||
|
Difficulty: *{difficulty:?}*\n\
|
||||||
|
{description}",
|
||||||
|
id = quest.id,
|
||||||
|
name = quest.name,
|
||||||
|
reward = quest.reward,
|
||||||
|
difficulty = quest.difficulty,
|
||||||
|
description = quest.description,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
prefix_command,
|
prefix_command,
|
||||||
slash_command,
|
slash_command,
|
||||||
subcommands("list", "create", "update"),
|
subcommands("list", "create", "update", "publish"),
|
||||||
)]
|
)]
|
||||||
pub async fn quest(
|
pub async fn quest(
|
||||||
_ctx: Context<'_>,
|
_ctx: Context<'_>,
|
||||||
|
|
@ -199,6 +212,7 @@ pub async fn update(
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let new_quest = Quest {
|
let new_quest = Quest {
|
||||||
id,
|
id,
|
||||||
difficulty,
|
difficulty,
|
||||||
|
|
@ -211,6 +225,37 @@ pub async fn update(
|
||||||
deadline: dead_line,
|
deadline: dead_line,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if new_quest.public {
|
||||||
|
let content = make_quest_message_content(&new_quest);
|
||||||
|
let builder = EditMessage::new().content(content);
|
||||||
|
|
||||||
|
let channel = {
|
||||||
|
let dc = ctx.data().discord.clone();
|
||||||
|
let guard = dc.lock().expect("shouldn't be locked");
|
||||||
|
guard.quests_channel
|
||||||
|
};
|
||||||
|
let message = {
|
||||||
|
let messages = channel.messages_iter(ctx)
|
||||||
|
.filter_map(|m| async move { if m.is_ok() { Some(m.unwrap()) } else {
|
||||||
|
eprintln!("{}", m.unwrap_err());
|
||||||
|
None
|
||||||
|
} })
|
||||||
|
.filter(|m| {
|
||||||
|
future::ready(m.content.contains(&format!("#{id}")))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>().await;
|
||||||
|
messages.first().cloned()
|
||||||
|
};
|
||||||
|
if let Some(mut message) = message {
|
||||||
|
message.edit(ctx, builder).await?;
|
||||||
|
} else {
|
||||||
|
let reply_string = format!("Quest #{id} is public, but its message was not found in the {channel}",
|
||||||
|
channel = channel.mention()
|
||||||
|
);
|
||||||
|
ctx.reply(reply_string).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let path = conf.full_quests_path();
|
let path = conf.full_quests_path();
|
||||||
let reply_string = match new_quest.save(path) {
|
let reply_string = match new_quest.save(path) {
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
|
@ -223,3 +268,71 @@ pub async fn update(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[poise::command(
|
||||||
|
prefix_command,
|
||||||
|
slash_command,
|
||||||
|
required_permissions = "ADMINISTRATOR",
|
||||||
|
guild_only
|
||||||
|
)]
|
||||||
|
pub async fn publish(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "Identifier of the quest to publish"]
|
||||||
|
id: u16,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut quests = ctx.data().config.load_quests();
|
||||||
|
|
||||||
|
let Some(quest) = quests.iter_mut().find(|q| q.id == id) else {
|
||||||
|
let reply_string = format!("Quest #{id} not found");
|
||||||
|
ctx.reply(reply_string).await?;
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
if quest.public {
|
||||||
|
let reply_string = format!("Quest #{id} is already public");
|
||||||
|
ctx.reply(reply_string).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
quest.public = true;
|
||||||
|
|
||||||
|
let content = make_quest_message_content(&quest);
|
||||||
|
|
||||||
|
let builder = CreateMessage::new()
|
||||||
|
.content(content);
|
||||||
|
|
||||||
|
let dc = ctx.data().discord.clone();
|
||||||
|
let channel = {
|
||||||
|
let guard = dc.lock().expect("shouldn't be locked");
|
||||||
|
guard.quests_channel
|
||||||
|
};
|
||||||
|
|
||||||
|
let message = channel.send_message(ctx, builder).await?;
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
let mut guard = dc.lock().expect("shouldn't be locked");
|
||||||
|
guard.quests_messages.push(message.id);
|
||||||
|
let path = ctx.data().config.full_impl_path().unwrap();
|
||||||
|
guard.save(path.parent().unwrap_or(Path::new("")).to_owned())
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = result {
|
||||||
|
eprintln!("{error}");
|
||||||
|
let reply_string = ERROR_MSG.to_string();
|
||||||
|
ctx.reply(reply_string).await?;
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let quests_path = ctx.data().config.full_quests_path();
|
||||||
|
if let Err(error) = quest.save(quests_path) {
|
||||||
|
eprintln!("{error}");
|
||||||
|
let reply_string = ERROR_MSG.to_string();
|
||||||
|
ctx.reply(reply_string).await?;
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let reply_string = format!("Published quest #{id}");
|
||||||
|
ctx.reply(reply_string).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue