SDK
Use the Flora TypeScript SDK to build bot scripts that run inside the Flora runtime. In the runtime, SDK functions are available globally (no imports needed).
Quickstart
ts
const ping = prefix({
name: "ping",
description: "Respond with pong",
run: async (ctx) => {
const extra = ctx.args.join(" ") || "none";
await ctx.reply(`pong! args: ${extra}`);
}
});
createBot({
prefix: "!",
commands: [ping]
});Event handlers
ts
on("ready", async (ctx) => {
console.log("bot ready");
});
on("messageCreate", async (ctx) => {
if (ctx.msg.author?.bot) return;
if (ctx.msg.content === "!hello") {
await ctx.reply("hello!");
}
});
on("messageUpdate", async (ctx) => {
console.log("message updated", ctx.msg.id);
});
on("messageDelete", async (ctx) => {
console.log("message deleted", ctx.msg.id);
});
on("messageDeleteBulk", async (ctx) => {
console.log("bulk delete", ctx.msg.ids.length);
});
on("interactionCreate", async (ctx) => {
console.log("interaction", ctx.msg.commandName);
});Prefix commands
ts
const greet = prefix({
name: "greet",
description: "Greet someone",
run: async (ctx) => {
const name = ctx.args[0] || "world";
await ctx.reply(`Hello, ${name}!`);
}
});
createBot({
prefix: "!",
commands: [greet]
});Slash commands
ts
const echo = slash({
name: "echo",
description: "Echo your input",
options: [
{ name: "text", description: "Text to echo", type: "string", required: true }
],
run: async (ctx) => {
const text = ctx.options.text as string;
await ctx.reply({ content: text, ephemeral: true });
}
});
createBot({
slashCommands: [echo]
});Slash command subcommands
ts
const settings = slash({
name: "settings",
description: "Manage settings",
subcommands: [
{
name: "get",
description: "Get a setting",
options: [{ name: "key", description: "Setting key", type: "string", required: true }],
run: async (ctx) => {
const key = ctx.options.key as string;
await ctx.reply(`Setting ${key}: ...`);
}
},
{
name: "set",
description: "Set a setting",
options: [
{ name: "key", description: "Setting key", type: "string", required: true },
{ name: "value", description: "Setting value", type: "string", required: true }
],
run: async (ctx) => {
const { key, value } = ctx.options as { key: string; value: string };
await ctx.reply(`Set ${key} = ${value}`);
}
}
]
});
createBot({ slashCommands: [settings] });Replies and edits
ts
await ctx.reply("simple reply");
await ctx.reply({
content: "rich reply",
ephemeral: true,
allowedMentions: { parse: ["users"] }
});
await ctx.edit("edited content");Embeds
ts
const status = embed()
.setTitle("Status")
.setDescription("All systems nominal")
.setColor(0x00ff00)
.addField("Uptime", "99.9%", true)
.addField("Latency", "42ms", true)
.setFooter("Flora")
.toJSON();
await ctx.reply({ embeds: [status] });KV store
ts
const store = kv.store("settings");
await store.set("prefix", "!");
const prefixValue = await store.get("prefix");
await store.set("session", JSON.stringify({ userId: "123" }), {
expiration: Math.floor(Date.now() / 1000) + 3600,
metadata: { source: "login" }
});
const { value, metadata } = await store.getWithMetadata("session");
const page = await store.list({ prefix: "user:", limit: 100 });
if (!page.list_complete) {
await store.list({ cursor: page.cursor });
}Utilities
ts
if (hasRole(ctx, "123456789")) {
await ctx.reply("role ok");
}
const sub = getSubcommand(ctx);
const group = getSubcommandGroup(ctx);Types
Types are generated from the Rust runtime and available in the SDK. Use these when authoring bot scripts and tests outside of the runtime bundle.