use std::time::{SystemTime, UNIX_EPOCH};
use vector_sdk::VectorBot;
#[tokio::main]
async fn main() -> vector_sdk::Result<()> {
let name = std::env::var("BOT_NAME").unwrap_or_else(|_| "Dicey".to_string());
let about = "A dice-flavoured slash-command bot built with vector_sdk. Type / for commands.";
let mut builder = VectorBot::builder().public();
if let Ok(nsec) = std::env::var("VECTOR_NSEC") {
builder = builder.nsec(nsec);
}
if let Ok(dir) = std::env::var("VECTOR_DATA_DIR") {
builder = builder.data_dir(dir);
}
let bot = builder.build().await?;
println!("── {name} online as {}", bot.npub());
{
let bot = bot.clone();
let name = name.clone();
tokio::spawn(async move {
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
let ok = bot.core().update_bot_profile(&name, "", "", about).await;
println!("── profile publish {}", if ok { "✅" } else { "FAILED" });
});
}
if let Some(invite) = std::env::args().nth(1) {
println!("── joining via link…");
let summary = bot.core().join_community(&invite).await?;
let cname = summary.get("name").and_then(|v| v.as_str()).unwrap_or("?");
println!("── joined \"{cname}\"");
}
bot.command("echo", "Repeat your text back")
.string("text", "What to repeat", true)
.run(|ctx| async move {
let text = ctx.str("text").unwrap_or_default().to_string();
let _ = ctx.reply(text).await;
});
bot.command("roll", "Roll a die")
.int("sides", "How many sides (default 6)", false)
.run(|ctx| async move {
let sides = ctx.int("sides").unwrap_or(6).clamp(2, 1_000_000);
let roll = (now_ms() as i64 % sides) + 1;
let _ = ctx.reply(format!("🎲 rolled {roll} on a d{sides}")).await;
});
bot.command("flip", "Flip a coin").run(|ctx| async move {
let side = if now_ms() % 2 == 0 { "heads" } else { "tails" };
let _ = ctx.reply(format!("🪙 {side}!")).await;
});
bot.command("eightball", "Ask the magic 8-ball")
.string("question", "Your question", true)
.run(|ctx| async move {
const ANSWERS: &[&str] = &[
"It is certain.", "Without a doubt.", "Ask again later.",
"Better not tell you now.", "Don't count on it.", "Very doubtful.",
];
let answer = ANSWERS[(now_ms() as usize) % ANSWERS.len()];
let _ = ctx.reply(format!("🎱 {answer}")).await;
});
bot.command("stress", "UI stress test: maximum-length choices")
.choice(
"pick",
"Choose one (wire-max lengths, mixed case, spaces)",
["abcdefghijklmnopqrstuvwxyz-12345", "This Is A Mixed Case Answer 1234", "UPPERCASE", "short"],
true,
)
.run(|ctx| async move {
let _ = ctx.reply(format!("you picked: {}", ctx.str("pick").unwrap_or_default())).await;
});
bot.command("about", "What am I?").run(move |ctx| async move {
let _ = ctx.reply("I'm a slash-command bot built with vector_sdk. My commands come from my published manifest.").await;
});
println!("── listening. Type / in a chat with me.\n");
bot.on_message(|_bot, _msg| async move {
})
.await?;
Ok(())
}
fn now_ms() -> u64 {
SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_millis() as u64).unwrap_or(0)
}