UNPKG

@gwigz/homunculus-bot

Version:

A bot framework for creating Second Life bots with chat commands and LSL communication

137 lines (134 loc) 3.81 kB
// src/api.ts import { Constants } from "@gwigz/homunculus-core"; var ApiHandler = class { client; prefix; separator; channel; handlers = /* @__PURE__ */ new Map(); onError; constructor(client, options) { this.client = client; this.prefix = options.apiPrefix ?? "#api"; this.separator = options.apiSeparator ?? ","; this.channel = options.apiChannel ?? -81513312; this.onError = options.onError; } registerHandler(handler) { this.handlers.set(handler.action, handler); } async handleChatMessage(chat) { if (chat.sourceType !== Constants.ChatSources.OBJECT || chat.chatType !== Constants.ChatTypes.OWNERSAY || !chat.message.startsWith(this.prefix)) { return; } try { const [action, data] = chat.message.substring(this.prefix.length + 1).split(this.separator, 2); if (!action) { return; } const handler = this.handlers.get(action); if (handler) { const response = await handler.process( this.client, this.parseData(handler, data ?? ""), chat ); if (typeof response === "string" && response.length > 0) { this.client.nearby.say(response, this.channel); } } } catch (error) { if (this.onError) { this.onError(error); } else if (this.onError !== false) { console.error(error); } } } parseData(handler, data) { const parsed = !handler.format || handler.format === "string" ? data : JSON.parse(data); if (handler.schema) { return handler.schema.parse(parsed); } return parsed; } }; // src/commands.ts import { Constants as Constants2 } from "@gwigz/homunculus-core"; var CommandHandler = class { client; prefix; commands = /* @__PURE__ */ new Map(); onError; constructor(client, options) { this.client = client; this.prefix = options.commandPrefix; this.onError = options.onError; } registerCommand(command) { this.commands.set(command.action, command); } async handleChatMessage(chat) { try { if (!chat.message || chat.sourceType !== Constants2.ChatSources.AGENT || chat.chatType === Constants2.ChatTypes.TYPING || chat.chatType === Constants2.ChatTypes.STOPPED || !chat.message.startsWith(this.prefix)) { return; } const [action, parameters] = chat.message.slice(this.prefix.length).split(" ", 1); if (!action) { return; } const command = this.commands.get(action); if (command) { const response = await command.process( this.client, this.parseData(command, (parameters ?? "").trim()), chat ); if (typeof response === "string" && response.length > 0) { this.client.nearby.say(response); } } } catch (error) { if (this.onError) { this.onError(error); } else if (this.onError !== false) { console.error(error); } } } parseData(handler, data) { const parsed = !handler.format || handler.format === "string" ? data : JSON.parse(data); if (handler.schema) { return handler.schema.parse(parsed); } return parsed; } }; // src/bot.ts var Bot = class { commandHandler; apiHandler; constructor(client, options) { this.commandHandler = new CommandHandler(client, options); this.apiHandler = new ApiHandler(client, options); client.nearby.on("chat", (chat) => { this.commandHandler.handleChatMessage(chat); this.apiHandler.handleChatMessage(chat); }); } registerCommand(command) { return this.commandHandler.registerCommand(command); } registerApiHandler(handler) { return this.apiHandler.registerHandler(handler); } }; export { ApiHandler, Bot, CommandHandler };