paringboard/src/script.rs
2026-01-05 22:54:32 +09:00

63 lines
1.6 KiB
Rust

use std::collections::HashMap;
use anyhow::anyhow;
use rhai::{Dynamic, Engine, Map, Scope};
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub struct ReactionResult {
pub channel_id: String,
pub count: i64,
pub icon: String,
}
pub fn check(
script: &str,
reactions: HashMap<String, i64>,
channel: String,
) -> anyhow::Result<Option<ReactionResult>> {
let mut engine = Engine::new();
engine.set_max_operations(1000);
engine.register_type::<ReactionResult>();
engine.register_fn("result", |webhook_url: String, count: i64, icon: String| {
ReactionResult {
channel_id: webhook_url,
count,
icon,
}
});
engine
.disable_symbol("for")
.disable_symbol("while")
.disable_symbol("loop")
.set_max_expr_depths(50, 5)
.set_max_string_size(60)
.set_max_map_size(512)
.set_max_array_size(512);
let mut emotes_input = Map::new();
for (emoji, count) in reactions {
emotes_input.insert(emoji.into(), Dynamic::from(count));
}
let mut scope = Scope::new();
scope.set_value("reactions", Dynamic::from(emotes_input));
scope.set_value("channel", Dynamic::from(channel));
let result: Dynamic = engine
.eval_with_scope(&mut scope, script)
.map_err(|e| anyhow!("{e:?}"))?;
let result: Option<ReactionResult> = if result.is_unit() {
None
} else {
Some(
result
.try_cast_result()
.map_err(|e| anyhow!("failed to cast: {e:?}"))?,
)
};
return Ok(result);
}