This commit is contained in:
2025-07-05 13:34:24 +00:00
parent 5c51acc8d1
commit ff5c7506ff

View File

@ -10,14 +10,35 @@ import { PrismaClient } from "../generated/prisma/client.js";
const prisma = new PrismaClient();
const envConfig = {
pleromaInstanceUrl: process.env.PLEROMA_INSTANCE_URL || "",
pleromaInstanceDomain: process.env.PLEROMA_INSTANCE_DOMAIN || "",
onlyLocalReplies: process.env.ONLY_LOCAL_REPLIES === "true" ? true : false,
ollamaUrl: process.env.OLLAMA_URL || "",
ollamaSystemPrompt:
process.env.OLLAMA_SYSTEM_PROMPT ||
"You are a helpful AI assistant. Answer all questions concisely.",
ollamaModel: process.env.OLLAMA_MODEL || "",
fetchInterval: process.env.FETCH_INTERVAL
? parseInt(process.env.FETCH_INTERVAL)
: 15000,
bearerToken: process.env.INSTANCE_BEARER_TOKEN || "",
};
const ollamaConfig: OllamaConfigOptions = {
temperature: 0.3,
num_predict: 400,
};
const getNotifications = async () => {
const { bearerToken, pleromaInstanceUrl } = envConfig;
try {
const request = await fetch(
`${process.env.PLEROMA_INSTANCE_URL}/api/v1/notifications?types[]=mention`,
`${pleromaInstanceUrl}/api/v1/notifications?types[]=mention`,
{
method: "GET",
headers: {
Authorization: `Bearer ${process.env.INSTANCE_BEARER_TOKEN}`,
Authorization: `Bearer ${bearerToken}`,
},
}
);
@ -82,11 +103,12 @@ const storePromptData = async (
}
};
const trimInputData = (input: string) => {
const trimInputData = (input: string): string => {
const strippedInput = striptags(input);
const split = strippedInput.split(" ");
const promptStringIndex = split.indexOf("!prompt");
return split.slice(promptStringIndex + 1).join(" "); // returns everything after the !prompt
split.splice(promptStringIndex, 1);
return split.join(" "); // returns everything after the !prompt
};
const recordPendingResponse = async (notification: Notification) => {
@ -104,6 +126,13 @@ const recordPendingResponse = async (notification: Notification) => {
const generateOllamaRequest = async (
notification: Notification
): Promise<OllamaResponse | undefined> => {
const {
onlyLocalReplies,
pleromaInstanceDomain,
ollamaModel,
ollamaSystemPrompt,
ollamaUrl,
} = envConfig;
try {
if (
striptags(notification.status.content).includes("!prompt") &&
@ -111,10 +140,8 @@ const generateOllamaRequest = async (
notification.type === "mention"
) {
if (
process.env.ONLY_LOCAL_REPLIES === "true" &&
!notification.status.account.fqn.includes(
`@${process.env.PLEROMA_INSTANCE_DOMAIN}`
)
onlyLocalReplies &&
!notification.status.account.fqn.includes(`@${pleromaInstanceDomain}`)
) {
return;
}
@ -123,20 +150,16 @@ const generateOllamaRequest = async (
}
await recordPendingResponse(notification);
await storeUserData(notification);
const ollamaConfig: OllamaConfigOptions = {
temperature: 1.2,
num_predict: 400,
};
const ollamaRequestBody: OllamaRequest = {
model: process.env.OLLAMA_MODEL as string,
system: process.env.OLLAMA_SYSTEM_PROMPT as string,
model: ollamaModel,
system: ollamaSystemPrompt,
prompt: `@${notification.status.account.fqn} says: ${trimInputData(
notification.status.content
)}`,
stream: false,
options: ollamaConfig,
};
const response = await fetch(`${process.env.OLLAMA_URL}/api/generate`, {
const response = await fetch(`${ollamaUrl}/api/generate`, {
method: "POST",
body: JSON.stringify(ollamaRequestBody),
});
@ -153,6 +176,7 @@ const postReplyToStatus = async (
notification: Notification,
ollamaResponseBody: OllamaResponse
) => {
const { pleromaInstanceUrl, bearerToken } = envConfig;
try {
let mentions: string[];
const statusBody: NewStatusBody = {
@ -170,17 +194,14 @@ const postReplyToStatus = async (
statusBody.to = mentions;
}
const response = await fetch(
`${process.env.PLEROMA_INSTANCE_URL}/api/v1/statuses`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INSTANCE_BEARER_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify(statusBody),
}
);
const response = await fetch(`${pleromaInstanceUrl}/api/v1/statuses`, {
method: "POST",
headers: {
Authorization: `Bearer ${bearerToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(statusBody),
});
if (!response.ok) {
throw new Error(`New status request failed: ${response.statusText}`);
@ -193,6 +214,7 @@ const postReplyToStatus = async (
};
const deleteNotification = async (notification: Notification) => {
const { pleromaInstanceUrl, bearerToken } = envConfig;
try {
if (!notification.id) {
return;
@ -203,11 +225,11 @@ const deleteNotification = async (notification: Notification) => {
data: { isProcessing: false },
});
const response = await fetch(
`${process.env.PLEROMA_INSTANCE_URL}/api/v1/notifications/${notification.id}/dismiss`,
`${pleromaInstanceUrl}/api/v1/notifications/${notification.id}/dismiss`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INSTANCE_BEARER_TOKEN}`,
Authorization: `Bearer ${bearerToken}`,
},
}
);
@ -221,10 +243,6 @@ const deleteNotification = async (notification: Notification) => {
}
};
const fetchInterval = process.env.FETCH_INTERVAL
? parseInt(process.env.FETCH_INTERVAL)
: 15000;
let notifications = [];
const beginFetchCycle = async () => {
setInterval(async () => {
@ -243,12 +261,12 @@ const beginFetchCycle = async () => {
})
);
}
}, fetchInterval); // lower intervals may cause the bot to respond multiple times to the same message, but we try to mitigate this with the deleteNotification function
}, envConfig.fetchInterval); // lower intervals may cause the bot to respond multiple times to the same message, but we try to mitigate this with the deleteNotification function
};
console.log(
`Fetching notifications from ${process.env.PLEROMA_INSTANCE_DOMAIN}, every ${
fetchInterval / 1000
`Fetching notifications from ${envConfig.pleromaInstanceDomain}, every ${
envConfig.fetchInterval / 1000
} seconds.`
);
await beginFetchCycle();