// // Copyright © 2024 Hardcore Engineering Inc. // // Licensed under the Eclipse Public License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. You may // obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // limitations under the License. // import { ChatMessage } from '@hcengineering/chunter' import { AttachedDoc, Tx, TxCreateDoc, TxCUD } from '@hcengineering/core' import { ActivityInboxNotification, MentionInboxNotification } from '@hcengineering/notification' import { TriggerControl } from '@hcengineering/server-core' // async function isDirectAvailable (direct: DirectMessage, control: TriggerControl): Promise { // const { members } = direct // if (!members.includes(aiBot.account.AIBot)) { // return false // } // const personAccounts = await control.modelDb.findAll(contact.class.PersonAccount, { // _id: { $in: members as PersonId[] } // }) // const persons = new Set(personAccounts.map((account) => account.person)) // return persons.size === 2 // } // async function getMessageDoc (message: ChatMessage, control: TriggerControl): Promise { // if (control.hierarchy.isDerived(message._class, chunter.class.ThreadMessage)) { // const thread = message as ThreadMessage // const _id = thread.objectId // const _class = thread.objectClass // return (await control.findAll(control.ctx, _class, { _id }))[0] // } else { // const _id = message.attachedTo // const _class = message.attachedToClass // return (await control.findAll(control.ctx, _class, { _id }))[0] // } // } // function getMessageData (doc: Doc, message: ChatMessage, email: string): AIMessageEventRequest { // return { // type: AIEventType.Message, // createdOn: message.createdOn ?? message.modifiedOn, // objectId: message.attachedTo, // objectClass: message.attachedToClass, // objectSpace: doc.space, // collection: message.collection, // messageClass: message._class, // messageId: message._id, // message: message.message, // user: message.createdBy ?? message.modifiedBy, // email // } // } // function getThreadMessageData (message: ThreadMessage, email: string): AIMessageEventRequest { // return { // type: AIEventType.Message, // createdOn: message.createdOn ?? message.modifiedOn, // objectId: message.attachedTo, // objectClass: message.attachedToClass, // objectSpace: message.space, // collection: message.collection, // messageClass: message._class, // message: message.message, // messageId: message._id, // user: message.createdBy ?? message.modifiedBy, // email // } // } // async function getThreadParent (control: TriggerControl, message: ChatMessage): Promise | undefined> { // if (!control.hierarchy.isDerived(message.attachedToClass, chunter.class.ChatMessage)) { // return undefined // } // const parentInfo = ( // await control.findAll(control.ctx, message.attachedToClass, { // _id: message.attachedTo as Ref, // [aiBot.mixin.TransferredMessage]: { $exists: true } // }) // )[0] // if (parentInfo !== undefined) { // return control.hierarchy.as(parentInfo, aiBot.mixin.TransferredMessage).messageId // } // return message.attachedTo as Ref // } // async function createTransferEvent ( // control: TriggerControl, // message: ChatMessage, // account: any, // data: AIMessageEventRequest // ): Promise { // if (account.role !== AccountRole.Owner) { // return // } // const supportWorkspaceId = getSupportWorkspaceId() // if (supportWorkspaceId === undefined) { // return // } // return { // type: AIEventType.Transfer, // createdOn: message.createdOn ?? message.modifiedOn, // messageClass: data.messageClass, // message: message.message, // collection: data.collection, // toWorkspace: supportWorkspaceId, // toPersonId: account, // fromWorkspace: control.workspace.uuid, // // fromWorkspaceName: control.workspace.workspaceName, // fromWorkspaceUrl: control.workspace.url, // messageId: message._id, // parentMessageId: await getThreadParent(control, message) // } // } // eslint-disable-next-line @typescript-eslint/no-unused-vars async function onBotDirectMessageSend (control: TriggerControl, message: ChatMessage): Promise { // TODO: FIXME // const account = control.modelDb.findAllSync(contact.class.PersonAccount, { // _id: (message.createdBy ?? message.modifiedBy) as PersonId // })[0] // if (account === undefined) { // return // } // const direct = (await getMessageDoc(message, control)) as DirectMessage // if (direct === undefined) { // return // } // const isAvailable = await isDirectAvailable(direct, control) // if (!isAvailable) { // return // } // let messageEvent: AIMessageEventRequest // if (control.hierarchy.isDerived(message._class, chunter.class.ThreadMessage)) { // messageEvent = getThreadMessageData(message as ThreadMessage, account.email) // } else { // messageEvent = getMessageData(direct, message, account.email) // } // const transferEvent = await createTransferEvent(control, message, account, messageEvent) // const events = transferEvent !== undefined ? [messageEvent, transferEvent] : [messageEvent] // await sendAIEvents(events, control.workspace.uuid, control.ctx) } // eslint-disable-next-line @typescript-eslint/no-unused-vars async function onSupportWorkspaceMessage (control: TriggerControl, message: ChatMessage): Promise { // TODO: FIXME // const supportWorkspaceId = getSupportWorkspaceId() // if (supportWorkspaceId === undefined) { // return // } // if (control.workspace.uuid !== supportWorkspaceId) { // return // } // if (!control.hierarchy.isDerived(message.attachedToClass, analyticsCollector.class.OnboardingChannel)) { // return // } // const channel = (await getMessageDoc(message, control)) as OnboardingChannel // if (channel === undefined) { // return // } // const { workspaceId, email } = channel // const account = control.modelDb.findAllSync(contact.class.PersonAccount, { // _id: (message.createdBy ?? message.modifiedBy) as PersonId // })[0] // let data: AIMessageEventRequest // if (control.hierarchy.isDerived(message._class, chunter.class.ThreadMessage)) { // data = getThreadMessageData(message as ThreadMessage, account.email) // } else { // data = getMessageData(channel, message, account.email) // } // const transferEvent: AITransferEventRequest = { // type: AIEventType.Transfer, // createdOn: data.createdOn, // messageClass: data.messageClass, // message: message.message, // collection: data.collection, // toEmail: email, // toWorkspace: workspaceId, // fromWorkspace: control.workspace.uuid, // fromWorkspaceUrl: control.workspace.url, // // fromWorkspaceName: control.workspace.workspaceName, // messageId: message._id, // parentMessageId: await getThreadParent(control, message) // } // await sendAIEvents([transferEvent], control.workspace.uuid, control.ctx) } export async function OnMessageSend (originTxs: TxCUD[], control: TriggerControl): Promise { // TODO: FIXME // const { hierarchy } = control // const txes = originTxs.filter( // (it) => // it._class === core.class.TxCreateDoc && // hierarchy.isDerived(it.objectClass, chunter.class.ChatMessage) && // !(it.modifiedBy === aiBot.account.AIBot || it.modifiedBy === core.account.System) // ) // if (txes.length === 0) { // return [] // } // for (const tx of txes) { // const isThread = hierarchy.isDerived(tx.objectClass, chunter.class.ThreadMessage) // const message = TxProcessor.createDoc2Doc(tx as TxCreateDoc) // // const docClass = isThread ? (message as ThreadMessage).objectClass : message.attachedToClass // // if (!hierarchy.isDerived(docClass, chunter.class.ChunterSpace)) { // continue // } // // if (docClass === chunter.class.DirectMessage) { // await onBotDirectMessageSend(control, message) // } // // if (docClass === analyticsCollector.class.OnboardingChannel) { // await onSupportWorkspaceMessage(control, message) // } // } return [] } export async function OnMention (tx: TxCreateDoc[], control: TriggerControl): Promise { // Note: temporally commented until open ai will be added // if (tx.objectClass !== notification.class.MentionInboxNotification || tx._class !== core.class.TxCreateDoc) { // return [] // } // // const mention = TxProcessor.createDoc2Doc(tx) // // if (mention.user !== aiBot.account.AIBot) { // return [] // } // // if (!control.hierarchy.isDerived(mention.mentionedInClass, chunter.class.ChatMessage)) { // return [] // } // // const message = ( // await control.findAll(mention.mentionedInClass, { _id: mention.mentionedIn as Ref }) // )[0] // // if (message === undefined) { // return [] // } // // await createResponseEvent(message, control) return [] } export async function OnMessageNotified ( tx: TxCreateDoc[], control: TriggerControl ): Promise { // Note: temporally commented until open ai will be added // if (tx.objectClass !== notification.class.ActivityInboxNotification || tx._class !== core.class.TxCreateDoc) { // return [] // } // // const doc = TxProcessor.createDoc2Doc(tx) // // if (doc.user !== aiBot.account.AIBot) { // return [] // } // // if (!control.hierarchy.isDerived(doc.attachedToClass, chunter.class.ChatMessage)) { // return [] // } // // const personAccount = await control.modelDb.findOne(contact.class.PersonAccount, { email: aiBotAccountEmail }) // // if (personAccount === undefined) { // return [] // } // // const message = ( // await control.findAll(doc.attachedToClass, { _id: doc.attachedTo as Ref }) // )[0] // // if (message === undefined) { // return [] // } // // if (isDocMentioned(personAccount.person, message.message)) { // return await createResponseEvent(message, control) // } // // if (!control.hierarchy.isDerived(message._class, chunter.class.ThreadMessage)) { // return [] // } // // const thread = message as ThreadMessage // TODO: do we really need to find parent??? // const parent = (await control.findAll(thread.attachedToClass, { _id: thread.attachedTo }))[0] // // if (parent === undefined) { // return [] // } // // if (parent.createdBy === aiBot.account.AIBot) { // return await createResponseEvent(message, control) // } return [] } export async function OnUserStatus (txes: Tx[], control: TriggerControl): Promise { // TODO: FIXME return [] // Not implemented // for (const originTx of txes) { // const tx = originTx as TxCUD // if ( // tx.objectClass !== core.class.UserStatus || // ![core.class.TxCreateDoc, core.class.TxUpdateDoc].includes(tx._class) // ) { // continue // } // if (tx._class === core.class.TxCreateDoc) { // const createTx = tx as TxCreateDoc // const status = TxProcessor.createDoc2Doc(createTx) // if (status.user === aiBot.account.AIBot || status.user === core.account.System || !status.online) { // continue // } // } // if (tx._class === core.class.TxUpdateDoc) { // const updateTx = tx as TxUpdateDoc // const val = updateTx.operations.online // if (val !== true) { // continue // } // const status = (await control.findAll(control.ctx, core.class.UserStatus, { _id: updateTx.objectId }))[0] // if (status === undefined || status.user === aiBot.account.AIBot || status.user === core.account.System) { // continue // } // } // const account = control.modelDb.findAllSync(contact.class.PersonAccount, { email: aiBotAccountEmail })[0] // if (account !== undefined) { // continue // } // await createAccountRequest(control.workspace, control.ctx) // } // return [] } // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export default async () => ({ trigger: { OnMessageSend, OnMention, OnMessageNotified, OnUserStatus } })