2023-02-02 12:44:14 +00:00
|
|
|
import { ChatGPTAPI, ChatMessage } from "chatgpt";
|
2023-01-08 20:19:43 +00:00
|
|
|
import Markdown from 'markdown-it';
|
2022-12-29 11:11:52 +00:00
|
|
|
import { MatrixClient } from "matrix-bot-sdk";
|
2023-01-12 18:03:23 +00:00
|
|
|
import { MessageEvent, StoredConversation } from "./interfaces.js";
|
|
|
|
import { CHATGPT_TIMEOUT } from "./env.js";
|
2022-12-09 09:41:17 +00:00
|
|
|
|
2023-01-08 20:19:43 +00:00
|
|
|
const md = Markdown();
|
|
|
|
|
2022-12-09 09:41:17 +00:00
|
|
|
export function parseMatrixUsernamePretty(matrix_username: string): string {
|
|
|
|
if (matrix_username.includes(":") === false || matrix_username.includes("@") === false) {
|
|
|
|
return matrix_username;
|
|
|
|
}
|
|
|
|
const withoutUrl = matrix_username.split(':')[0];
|
|
|
|
return withoutUrl.split('@')[1]
|
|
|
|
}
|
|
|
|
|
2023-01-07 00:30:09 +00:00
|
|
|
export function isEventAMessage(event: any): event is MessageEvent {
|
|
|
|
return event.type === 'm.room.message'
|
|
|
|
}
|
|
|
|
|
2022-12-29 11:11:52 +00:00
|
|
|
export async function sendError(client: MatrixClient, text: string, roomId: string, eventId: string): Promise<void> {
|
|
|
|
Promise.all([client.setTyping(roomId, false, 500), client.sendText(roomId, text), client.sendReadReceipt(roomId, eventId)]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a thread reply.
|
2023-01-08 20:19:43 +00:00
|
|
|
* @param {MatrixClient} client Matrix client
|
|
|
|
* @param {string} roomId the room ID the event being replied to resides in
|
|
|
|
* @param {string} rootEventId the root event of the thread
|
|
|
|
* @param {string} text the plain text to reply with
|
2023-01-27 17:45:41 +00:00
|
|
|
* @param {boolean} thread reply as a thread
|
2023-01-08 20:19:43 +00:00
|
|
|
* @param {boolean} rich should the plain text be rendered to html using markdown?
|
2022-12-29 11:11:52 +00:00
|
|
|
*/
|
2023-01-27 17:45:41 +00:00
|
|
|
export async function sendReply(client: MatrixClient, roomId: string, rootEventId: string, text: string, thread: boolean = false, rich:boolean = false): Promise<void> {
|
2023-01-08 20:19:43 +00:00
|
|
|
|
|
|
|
const contentCommon = {
|
2022-12-29 11:11:52 +00:00
|
|
|
body: text,
|
|
|
|
msgtype: "m.text",
|
2023-01-27 17:45:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const contentThreadOnly = {
|
2022-12-29 11:11:52 +00:00
|
|
|
"m.relates_to": {
|
2023-01-08 20:19:43 +00:00
|
|
|
event_id: rootEventId,
|
2022-12-29 11:11:52 +00:00
|
|
|
is_falling_back: true,
|
|
|
|
"m.in_reply_to": {
|
2023-01-08 20:19:43 +00:00
|
|
|
"event_id": rootEventId
|
2022-12-29 11:11:52 +00:00
|
|
|
},
|
|
|
|
rel_type: "m.thread"
|
|
|
|
}
|
|
|
|
}
|
2023-01-08 20:19:43 +00:00
|
|
|
|
|
|
|
const contentTextOnly = {
|
|
|
|
"org.matrix.msc1767.text": text,
|
|
|
|
}
|
|
|
|
|
|
|
|
const renderedText = md.render(text)
|
|
|
|
|
|
|
|
const contentRichOnly = {
|
|
|
|
format: "org.matrix.custom.html",
|
|
|
|
formatted_body: renderedText,
|
|
|
|
"org.matrix.msc1767.message": [
|
|
|
|
{
|
|
|
|
"body": text,
|
|
|
|
"mimetype": "text/plain"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"body": renderedText,
|
|
|
|
"mimetype": "text/html"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
const content = rich ? { ...contentCommon, ...contentRichOnly } : { ...contentCommon, ...contentTextOnly };
|
2023-01-27 17:45:41 +00:00
|
|
|
const finalContent = thread ? { ...content, ...contentThreadOnly } : content
|
2023-01-08 20:19:43 +00:00
|
|
|
|
2023-01-27 17:45:41 +00:00
|
|
|
await client.sendEvent(roomId, "m.room.message", finalContent);
|
2022-12-29 11:11:52 +00:00
|
|
|
}
|
2023-01-12 18:03:23 +00:00
|
|
|
|
2023-02-02 12:44:14 +00:00
|
|
|
export async function sendChatGPTMessage(chatGPT: ChatGPTAPI, question: string, storedConversation: StoredConversation) {
|
|
|
|
let result: ChatMessage
|
2023-01-12 18:03:23 +00:00
|
|
|
if (storedConversation !== undefined) {
|
|
|
|
result = await chatGPT.sendMessage(question, {
|
|
|
|
timeoutMs: CHATGPT_TIMEOUT,
|
|
|
|
conversationId: storedConversation.conversationId,
|
|
|
|
parentMessageId: storedConversation.messageId
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
result = await chatGPT.sendMessage(question, { timeoutMs: CHATGPT_TIMEOUT });
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|