export enum SubjectType { BOT , USER , ADMIN , GROUP , ALL } export enum DirectionType { INCOMING , OUTGOING } export enum ModeType { SPEAK , TYPE } export class Subject { public readonly type : SubjectType ; public readonly who ? : string ; constructor ( type , who ? ) { this . type = type ; if ( who ) { this . who = who ; } } } export abstract class UiAction { [ key ] : any ; abstract render ( ) ; constructor ( init ? ) { Object . assign ( this , init ) ; } } export class ChatMessage < T extends UiAction | string > { public readonly direction : DirectionType ; public readonly from ? : Subject ; public readonly to ? : Subject ; public readonly content : T ; public readonly timestamp : Date ; public readonly isRead : boolean ; public readonly mode ? : ModeType ; constructor ( init ? ) { Object . assign ( this , init ) ; } static fromBotMessage ( content ) { return new ChatMessage ( { direction : DirectionType . INCOMING , from : new Subject ( SubjectType . BOT ) , to : new Subject ( SubjectType . USER ) , content , timestamp : new Date ( ) , isRead : false , } ) ; } static fromUserMessage ( content , mode ) { return new ChatMessage ( { direction : DirectionType . OUTGOING , from : new Subject ( SubjectType . USER ) , to : new Subject ( SubjectType . BOT ) , content , timestamp : new Date ( ) , isRead : true , mode , } ) ; } public get isIncoming ( ) : boolean { return this . direction === DirectionType . INCOMING ; } public get isOutgoing ( ) : boolean { return this . direction === DirectionType . OUTGOING ; } public render ( ) { if ( this . content instanceof UiAction ) { return this . content . render ( ) ; } else { return this . content as string ; } } } export class Conversation { public id : string ; messages : ChatMessage < any > [ ] ; constructor ( id , messages = [ ] ) { this . id = id ; this . messages = messages ; } }