@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
JavaScript
// 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
};