mirror of
https://github.com/hexastack/hexabot
synced 2025-04-18 13:28:50 +00:00
412 lines
9.8 KiB
TypeScript
412 lines
9.8 KiB
TypeScript
/*
|
|
* Copyright © 2025 Hexastack. All rights reserved.
|
|
*
|
|
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
*/
|
|
|
|
import { Subscriber } from '@/chat/schemas/subscriber.schema';
|
|
import { AttachmentPayload } from '@/chat/schemas/types/attachment';
|
|
import { SubscriberChannelData } from '@/chat/schemas/types/channel';
|
|
import {
|
|
IncomingMessageType,
|
|
StdEventType,
|
|
StdIncomingMessage,
|
|
} from '@/chat/schemas/types/message';
|
|
import { Payload } from '@/chat/schemas/types/quick-reply';
|
|
import { NLU } from '@/helper/types';
|
|
|
|
import { ChannelName } from '../types';
|
|
|
|
import ChannelHandler from './Handler';
|
|
|
|
export interface ChannelEvent {}
|
|
|
|
// eslint-disable-next-line prettier/prettier
|
|
export default abstract class EventWrapper<
|
|
A extends {
|
|
eventType: StdEventType;
|
|
messageType?: IncomingMessageType;
|
|
raw: E;
|
|
},
|
|
E,
|
|
N extends ChannelName = ChannelName,
|
|
C extends ChannelHandler = ChannelHandler<N>,
|
|
S = SubscriberChannelDict[N],
|
|
> {
|
|
_adapter: A = { raw: {}, eventType: StdEventType.unknown } as A;
|
|
|
|
_handler: C;
|
|
|
|
channelAttrs: S;
|
|
|
|
_profile!: Subscriber;
|
|
|
|
_nlp!: NLU.ParseEntities;
|
|
|
|
/**
|
|
* Constructor : Class used to wrap any channel's event in order
|
|
* to provide a unified interface for accessing data by the chatbot.
|
|
*
|
|
* Any method declared in this class should be extended and overridden in any given channel's
|
|
* event wrapper if needed.
|
|
* @param handler - The channel's handler
|
|
* @param event - The message event received
|
|
* @param channelAttrs - Channel's specific data
|
|
*/
|
|
constructor(handler: C, event: A['raw'], channelAttrs: S = {} as S) {
|
|
this._handler = handler;
|
|
this._init(event);
|
|
this.channelAttrs = channelAttrs;
|
|
}
|
|
|
|
toString() {
|
|
return JSON.stringify(
|
|
{
|
|
handler: this._handler.getName(),
|
|
channelData: this.getChannelData(),
|
|
sender: this.getSender(),
|
|
// recipient: this.getRecipientForeignId(),
|
|
eventType: this.getEventType(),
|
|
messageType: this.getMessageType(),
|
|
payload: this.getPayload(),
|
|
message: this.getMessage(),
|
|
attachments: this.getAttachments(),
|
|
deliveredMessages: this.getDeliveredMessages(),
|
|
watermark: this.getWatermark(),
|
|
},
|
|
null,
|
|
4,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Called by the parent constructor, it defines `_adapter` which should store :
|
|
*
|
|
* - `_adapter.eventType` : The type of event received
|
|
*
|
|
*- `_adapter.messageType` : The type of message when the event is a message.
|
|
*
|
|
*- `_adapter.raw` : Sets a typed object of the event raw data
|
|
* @param event - The message event received from a given channel
|
|
*/
|
|
abstract _init(event: A['raw']): void;
|
|
|
|
/**
|
|
* Retrieves the current channel handler.
|
|
*
|
|
* @returns The current instance of the channel handler.
|
|
*/
|
|
getHandler(): C {
|
|
return this._handler;
|
|
}
|
|
|
|
/**
|
|
* Retrieves channel data.
|
|
*
|
|
* @returns Returns any channel related data.
|
|
*/
|
|
getChannelData(): SubscriberChannelData<N> {
|
|
return {
|
|
name: this._handler.getName(),
|
|
...this.channelAttrs,
|
|
} as SubscriberChannelData<N>;
|
|
}
|
|
|
|
/**
|
|
* Returns the message id.
|
|
* @returns the message id.
|
|
*/
|
|
abstract getId(): string;
|
|
|
|
/**
|
|
* Sets an event attribute value
|
|
*
|
|
* @deprecated
|
|
* @param attr - Event attribute name
|
|
* @param value - The value to set for the specified attribute.
|
|
*/
|
|
set(attr: string, value: any) {
|
|
(this._adapter as any).raw[attr] = value;
|
|
}
|
|
|
|
/**
|
|
* Returns an event attribute value, default value if it does exist
|
|
*
|
|
* @deprecated
|
|
* @param attr - Event attribute name
|
|
* @param otherwise - Default value if attribute does not exist
|
|
*
|
|
* @returns The value of the specified attribute or the default value.
|
|
*/
|
|
get(attr: string, otherwise: any): any {
|
|
return attr in (this._adapter as any).raw
|
|
? ((this._adapter as any).raw as any)[attr]
|
|
: otherwise || {};
|
|
}
|
|
|
|
/**
|
|
* Returns attached NLP parse results
|
|
*
|
|
* @returns The parsed NLP entities, or null if not available.
|
|
*/
|
|
getNLP(): NLU.ParseEntities | null {
|
|
return this._nlp;
|
|
}
|
|
|
|
/**
|
|
* Attaches the NLP object to the event
|
|
*
|
|
* @param nlp - NLP parse results
|
|
*/
|
|
setNLP(nlp: NLU.ParseEntities) {
|
|
this._nlp = nlp;
|
|
}
|
|
|
|
/**
|
|
* Returns event sender/profile id (channel's id)
|
|
*
|
|
* @returns sender/profile id
|
|
*/
|
|
abstract getSenderForeignId(): string;
|
|
|
|
/**
|
|
* Returns event sender data
|
|
*
|
|
* @returns event sender data
|
|
*/
|
|
getSender(): Subscriber {
|
|
return this._profile;
|
|
}
|
|
|
|
/**
|
|
* Sets event sender data
|
|
*
|
|
* @param profile - Sender data
|
|
*/
|
|
setSender(profile: Subscriber) {
|
|
this._profile = profile;
|
|
}
|
|
|
|
/**
|
|
* Pre-Process the message event
|
|
*
|
|
* Child class can perform operations such as storing files as attachments.
|
|
*/
|
|
preprocess() {
|
|
// Nothing ...
|
|
return Promise.resolve();
|
|
}
|
|
|
|
/**
|
|
* Returns event recipient id
|
|
*
|
|
* @returns event recipient id
|
|
*/
|
|
abstract getRecipientForeignId(): string;
|
|
|
|
/**
|
|
* Returns the type of event received (message, delivery, read, ...)
|
|
*
|
|
* @returns The type of event received (message, delivery, read, ...)
|
|
*/
|
|
getEventType(): StdEventType {
|
|
return this._adapter.eventType;
|
|
}
|
|
|
|
/**
|
|
* Identifies the type of the message received
|
|
*
|
|
* @return The type of message
|
|
*/
|
|
getMessageType(): IncomingMessageType | undefined {
|
|
return this._adapter.messageType;
|
|
}
|
|
|
|
/**
|
|
* Return payload whenever user clicks on a button/quick_reply or sends an attachment, false otherwise
|
|
*
|
|
* @returns The payload content
|
|
*/
|
|
abstract getPayload(): Payload | string | undefined;
|
|
|
|
/**
|
|
* Returns the message in a standardized format
|
|
*
|
|
* @returns The received message
|
|
*/
|
|
abstract getMessage(): StdIncomingMessage;
|
|
|
|
/**
|
|
* Return the text message received
|
|
*
|
|
* @returns Received text message
|
|
*/
|
|
getText(): string {
|
|
const message = this.getMessage();
|
|
if ('text' in message) {
|
|
return message.text;
|
|
} else if ('serialized_text' in message) {
|
|
return message.serialized_text;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Returns the list of received attachments
|
|
*
|
|
* @returns Received attachments message
|
|
*/
|
|
abstract getAttachments(): AttachmentPayload[];
|
|
|
|
/**
|
|
* Returns the list of delivered messages
|
|
*
|
|
* @returns Array of message ids
|
|
*/
|
|
abstract getDeliveredMessages(): string[];
|
|
|
|
/**
|
|
* Returns the message's watermark
|
|
*
|
|
* @returns The message's watermark
|
|
*/
|
|
abstract getWatermark(): number;
|
|
}
|
|
|
|
type GenericEvent = { senderId: string; messageId: string };
|
|
type GenericEventAdapter = {
|
|
eventType: StdEventType.unknown;
|
|
messageType: IncomingMessageType.unknown;
|
|
raw: GenericEvent;
|
|
};
|
|
|
|
export class GenericEventWrapper extends EventWrapper<
|
|
GenericEventAdapter,
|
|
GenericEvent,
|
|
ChannelName
|
|
> {
|
|
/**
|
|
* Constructor : channel's event wrapper
|
|
*
|
|
* @param handler - The channel's handler
|
|
* @param event - The message event received
|
|
*/
|
|
constructor(handler: ChannelHandler, event: GenericEvent) {
|
|
super(handler, event);
|
|
}
|
|
|
|
/**
|
|
* Called by the parent constructor, it defines :
|
|
*
|
|
* - The type of event received
|
|
*
|
|
* - The type of message when the event is a message.
|
|
*
|
|
* - Sets a typed raw object of the event data
|
|
* @param event - The message event received
|
|
|
|
*/
|
|
_init(event: GenericEvent): void {
|
|
this._adapter.eventType = StdEventType.unknown;
|
|
this._adapter.messageType = IncomingMessageType.unknown;
|
|
this._adapter.raw = event;
|
|
}
|
|
|
|
/**
|
|
* Returns the message id
|
|
*
|
|
* @returns The message id
|
|
*/
|
|
getId(): string {
|
|
if (this._adapter.raw.messageId) {
|
|
return this._adapter.raw.messageId;
|
|
}
|
|
throw new Error('The message id `mid` is missing');
|
|
}
|
|
|
|
/**
|
|
* Returns event sender id
|
|
*
|
|
* @returns event sender id
|
|
*/
|
|
getSenderForeignId(): string {
|
|
if (this._adapter.raw.senderId) {
|
|
return this._adapter.raw.senderId;
|
|
}
|
|
throw new Error('The sender id is missing');
|
|
}
|
|
|
|
/**
|
|
* Returns event recipient id (channel's id)
|
|
*
|
|
* @returns Returns event recipient id
|
|
*/
|
|
getRecipientForeignId(): string {
|
|
throw new Error('The recipient id is missing');
|
|
}
|
|
|
|
/**
|
|
* Returns the type of event received
|
|
*
|
|
* @returns The type of event received
|
|
*/
|
|
getEventType(): StdEventType {
|
|
return this._adapter.eventType;
|
|
}
|
|
|
|
/**
|
|
* Finds out and returns the type of the event received from the channel
|
|
*
|
|
* @returns The type of message
|
|
*/
|
|
getMessageType(): IncomingMessageType {
|
|
return this._adapter.messageType;
|
|
}
|
|
|
|
/**
|
|
* Returns payload whenever user clicks on a button/quick_reply or sends an attachment
|
|
*
|
|
* @returns The payload content
|
|
*/
|
|
getPayload(): Payload | string | undefined {
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Returns a standard message format that can be stored in DB
|
|
*
|
|
* @returns Received message in standard format
|
|
*/
|
|
getMessage(): StdIncomingMessage {
|
|
throw new Error('Unknown incoming message type');
|
|
}
|
|
|
|
/**
|
|
* @returns A list of received attachments
|
|
* @deprecated - This method is deprecated
|
|
*/
|
|
getAttachments(): AttachmentPayload[] {
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Returns the delivered messages ids
|
|
*
|
|
* @returns return delivered messages ids
|
|
*/
|
|
getDeliveredMessages(): string[] {
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Returns the message's watermark (timestamp or equivalent).
|
|
*
|
|
* @returns The message's watermark
|
|
*/
|
|
getWatermark() {
|
|
return 0;
|
|
}
|
|
}
|