feat: script test command
This commit is contained in:
parent
e739c443ac
commit
f3eb1dc188
3 changed files with 158 additions and 8 deletions
|
|
@ -1,7 +1,12 @@
|
|||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use serenity::all::{
|
||||
CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption,
|
||||
CreateInputText, CreateLabel, CreateModal, CreateModalComponent, CreateTextDisplay,
|
||||
InputTextStyle, Permissions,
|
||||
CommandInteraction, CommandOptionType, CommandType, Context, CreateCommand,
|
||||
CreateCommandOption, CreateComponent, CreateContainer, CreateContainerComponent,
|
||||
CreateInputText, CreateInteractionResponseMessage, CreateLabel, CreateModal,
|
||||
CreateModalComponent, CreateTextDisplay, InputTextStyle, MessageFlags, Permissions,
|
||||
ResolvedTarget,
|
||||
};
|
||||
|
||||
use crate::handler::{Handler, get_guild};
|
||||
|
|
@ -17,6 +22,13 @@ pub fn config_command() -> CreateCommand<'static> {
|
|||
.default_member_permissions(Permissions::ADMINISTRATOR)
|
||||
}
|
||||
|
||||
pub fn script_test_command() -> CreateCommand<'static> {
|
||||
CreateCommand::new("test_script")
|
||||
.name_localized("ko", "스크립트 테스트")
|
||||
.kind(CommandType::Message)
|
||||
.default_member_permissions(Permissions::ADMINISTRATOR)
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub async fn process_starboard_command(
|
||||
&self,
|
||||
|
|
@ -27,6 +39,26 @@ impl Handler {
|
|||
return Ok(());
|
||||
};
|
||||
|
||||
if !interaction
|
||||
.member
|
||||
.as_ref()
|
||||
.and_then(|x| x.permissions)
|
||||
.map(|x| x.contains(Permissions::ADMINISTRATOR))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
interaction
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
serenity::all::CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("관리자 권한이 필요합니다")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// if let CommandType interaction.data.kind {}
|
||||
|
||||
for option in interaction.data.options() {
|
||||
|
|
@ -72,4 +104,102 @@ if reactions["⭐"] >= 3 {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn process_script_test_command(
|
||||
&self,
|
||||
ctx: &Context,
|
||||
interaction: &CommandInteraction,
|
||||
) -> anyhow::Result<()> {
|
||||
let Some(guild_id) = interaction.guild_id else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if !interaction
|
||||
.member
|
||||
.as_ref()
|
||||
.and_then(|x| x.permissions)
|
||||
.map(|x| x.contains(Permissions::ADMINISTRATOR))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
interaction
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
serenity::all::CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("관리자 권한이 필요합니다")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let target = interaction.data.target();
|
||||
|
||||
let target_message = target
|
||||
.and_then(|x| match x {
|
||||
ResolvedTarget::Message(msg) => Some(msg),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| anyhow!("no target message"))?;
|
||||
|
||||
let script = get_guild(&self.db, guild_id)
|
||||
.await?
|
||||
.and_then(|x| x.script)
|
||||
.unwrap_or("".to_string());
|
||||
|
||||
let channel = interaction
|
||||
.channel
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("no channel data"))?;
|
||||
|
||||
let channel = ctx.http.get_channel(channel.id()).await?;
|
||||
|
||||
debug!("selected message: {target_message:?}");
|
||||
|
||||
let reactions: HashMap<String, i64> = target_message
|
||||
.reactions
|
||||
.iter()
|
||||
.map(|x| (x.reaction_type.to_string(), x.count as i64))
|
||||
.collect();
|
||||
|
||||
let (result, buffer) = paringboard::script::check(
|
||||
&script,
|
||||
reactions,
|
||||
interaction.channel_id.to_string(),
|
||||
channel
|
||||
.guild()
|
||||
.and_then(|x| x.parent_id)
|
||||
.map(|x| x.to_string()),
|
||||
)
|
||||
.unwrap_or_else(|err| (None, format!("run failed: {err:?}")));
|
||||
|
||||
interaction
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
serenity::all::CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.flags(MessageFlags::IS_COMPONENTS_V2)
|
||||
.components(vec![
|
||||
CreateComponent::Container(
|
||||
// result text
|
||||
CreateContainer::new(vec![CreateContainerComponent::TextDisplay(
|
||||
CreateTextDisplay::new(format!(
|
||||
"## Result \n```rs\n{result:?}\n```"
|
||||
)),
|
||||
)]),
|
||||
),
|
||||
CreateComponent::Container(CreateContainer::new(vec![
|
||||
CreateContainerComponent::TextDisplay(CreateTextDisplay::new(
|
||||
format!("## Console Output \n```rs\n{}\n```", &buffer),
|
||||
)),
|
||||
])),
|
||||
])
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,10 @@ impl EventHandler for Handler {
|
|||
|
||||
if let Err(e) = context
|
||||
.http
|
||||
.create_global_commands(&vec![commands::config_command()])
|
||||
.create_global_commands(&vec![
|
||||
commands::config_command(),
|
||||
commands::script_test_command(),
|
||||
])
|
||||
.await
|
||||
{
|
||||
error!("Failed to register config command: {e:?}");
|
||||
|
|
@ -108,6 +111,11 @@ impl Handler {
|
|||
if command.data.name == "starboard" {
|
||||
self.process_starboard_command(ctx, command).await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
if command.data.name == "test_script" {
|
||||
self.process_script_test_command(ctx, command).await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
|
@ -164,6 +172,7 @@ impl Handler {
|
|||
.and_then(|x| x.parent_id)
|
||||
.map(|x| x.to_string()),
|
||||
)
|
||||
.map(|x| x.0)
|
||||
.inspect_err(|res| {
|
||||
error!("check failed: {res:?}");
|
||||
})?
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use rhai::{Dynamic, Engine, Map, Scope};
|
||||
|
|
@ -17,9 +20,10 @@ pub fn check(
|
|||
reactions: HashMap<String, i64>,
|
||||
channel: String,
|
||||
category: Option<String>,
|
||||
) -> anyhow::Result<Option<ReactionResult>> {
|
||||
) -> anyhow::Result<(Option<ReactionResult>, String)> {
|
||||
debug!("script: {script}");
|
||||
let mut engine = Engine::new();
|
||||
let buffer = Arc::new(RwLock::new(String::new()));
|
||||
engine.set_max_operations(1000);
|
||||
engine.register_type::<ReactionResult>();
|
||||
engine.register_fn("result", |webhook_url: String, count: i64, icon: String| {
|
||||
|
|
@ -30,6 +34,8 @@ pub fn check(
|
|||
}
|
||||
});
|
||||
|
||||
let logger = buffer.clone();
|
||||
|
||||
engine
|
||||
.disable_symbol("for")
|
||||
.disable_symbol("while")
|
||||
|
|
@ -37,7 +43,10 @@ pub fn check(
|
|||
.set_max_expr_depths(50, 5)
|
||||
.set_max_string_size(60)
|
||||
.set_max_map_size(512)
|
||||
.set_max_array_size(512);
|
||||
.set_max_array_size(512)
|
||||
.on_print(move |line| {
|
||||
logger.write().unwrap().push_str(line);
|
||||
});
|
||||
|
||||
let mut emotes_input = Map::new();
|
||||
for (emoji, count) in reactions {
|
||||
|
|
@ -57,6 +66,8 @@ pub fn check(
|
|||
},
|
||||
);
|
||||
|
||||
debug!("current scope: {scope:?}");
|
||||
|
||||
let result: Dynamic = engine
|
||||
.eval_with_scope(&mut scope, script)
|
||||
.map_err(|e| anyhow!("{e:?}"))?;
|
||||
|
|
@ -73,5 +84,5 @@ pub fn check(
|
|||
)
|
||||
};
|
||||
|
||||
return Ok(result);
|
||||
return Ok((result, buffer.read().unwrap().to_string()));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue