aslobot-matrix/src/modules/ai/ai.ts
2025-12-29 01:10:19 +01:00

125 lines
3.7 KiB
TypeScript

import { MatrixClient, MsgType } from "matrix-js-sdk";
import type { ICallbackStore } from "../types.js";
import { config } from "../../config.js";
import { getTextGemini, getImageGemini } from "../../services/ai/ai.js";
import { alts } from "./alts.js";
import type { IAIInstructions } from "./types.js";
import { getUserById, getUserName } from "../../helpers.js";
import { prices } from "./prices.js";
import { state } from "../../store/store.js";
let client: MatrixClient;
const registerModuleAI = (
matrixClient: MatrixClient,
callbackStore: ICallbackStore,
) => {
client = matrixClient;
callbackStore.messageCallbacks.push({
startConditions: [`${config.app.triggerPrefix}ai`],
callbackFunc: onAI,
allowedRoles: ["USER", "MODERATOR", "ADMIN"],
});
callbackStore.messageCallbacks.push({
startConditions: [`${config.app.triggerPrefix}img `],
callbackFunc: onImageGen,
allowedRoles: ["USER", "MODERATOR", "ADMIN"],
});
};
const onAI = async (
text: string,
roomId: string,
sender: string,
repliedMessage?: string,
repliedSender?: string,
) => {
const user = getUserById(sender);
const date = Date.now();
let personality = config.app.ai.personalities[state.personality.index];
if (date > state.personality.startTime + (personality?.timeout ?? 0)) {
const randomInt = Math.floor(
Math.random() * config.app.ai.personalities.length,
);
state.personality = {
index: randomInt,
startTime: date,
};
client.setDisplayName(
`AsloBot (${config.app.ai.personalities[state.personality.index]?.personalityName})`,
);
}
personality = config.app.ai.personalities[state.personality.index];
let textMod = text.replace("!ai", "").trim().toLowerCase();
let instructions = {
prefferedLanguages: ["english", "slovak"],
users: alts.map((alt) => ({
names: alt.keys,
alt: alt.alt,
backstory: alt.id
? getUserById(`${alt.id}:${config.server}`).information
: undefined,
})),
aiPersonality: personality?.personality ?? "",
aiLikes: personality?.likes ?? "",
aiDislikes: personality?.dislikes ?? "",
} as IAIInstructions;
const username = getUserName(user);
let repliedUsername = "";
if (repliedSender) {
repliedUsername = getUserName(getUserById(repliedSender));
}
const responseAI = await getTextGemini(
instructions,
`${username}: ${textMod}`,
`${repliedUsername}: ${repliedMessage}`,
);
user.aiCost += responseAI.tokens * prices.text;
client.sendTextMessage(roomId, responseAI.text);
};
const onImageGen = async (text: string, roomId: string, sender: string) => {
const user = getUserById(sender);
let textMod = text.replace("!img", "").trim().toLowerCase();
alts.forEach((alt) => {
alt.keys.forEach((key) => {
textMod = textMod.replaceAll(key, alt.alt);
});
});
const responseAI = await getImageGemini(textMod);
user.aiCost += responseAI.tokens * prices.image;
if (!responseAI.image || responseAI.image.length < 10) {
return;
}
const imageName = `photo-img-gen.png`;
const uploadResult = await client.uploadContent(responseAI.image, {
type: "image/png",
name: imageName,
});
await client.sendMessage(roomId, {
msgtype: MsgType.Image,
body: imageName,
url: uploadResult.content_uri,
info: {
mimetype: "image/png",
size: responseAI.image.length,
},
});
};
export { registerModuleAI, onImageGen };