Skip to content

Commit

Permalink
feat(core): render service (#4467)
Browse files Browse the repository at this point in the history
* basic

* renderForChannel

* move renderForChannel, card, choice

* more contents

* pipeline

* doc

* fix

* tests

* eslint

* experimental

* __unrendered instead of rendered

* fix middleware

* move types out of experimental

* warning

* remove leftover function

* move out of middleware and into sendEvent for now

* fix merge

* more tests

* fix test

* more tests

* fix import
  • Loading branch information
samuelmasse committed Mar 11, 2021
1 parent aaabd6a commit 1a6e953
Show file tree
Hide file tree
Showing 9 changed files with 717 additions and 6 deletions.
29 changes: 25 additions & 4 deletions src/bp/core/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { MessageService } from './services/messaging/messages'
import { StateManager } from './services/middleware/state-manager'
import { NotificationsService } from './services/notification/service'
import RealtimeService from './services/realtime'
import { RenderService } from './services/render/render'
import { WorkspaceService } from './services/workspace-service'
import { TYPES } from './types'

Expand Down Expand Up @@ -213,13 +214,15 @@ const distributed = (jobService: JobService): typeof sdk.distributed => {
const experimental = (
hookService: HookService,
conversationService: ConversationService,
messageService: MessageService
messageService: MessageService,
renderService: RenderService
): typeof sdk.experimental => {
return {
disableHook: hookService.disableHook.bind(hookService),
enableHook: hookService.enableHook.bind(hookService),
conversations: conversations(conversationService),
messages: messages(messageService)
messages: messages(messageService),
render: render(renderService)
}
}

Expand All @@ -235,6 +238,23 @@ const messages = (messageService: MessageService): typeof sdk.experimental.messa
}
}

const render = (renderService: RenderService): typeof sdk.experimental.render => {
return {
text: renderService.renderText.bind(renderService),
image: renderService.renderImage.bind(renderService),
card: renderService.renderCard.bind(renderService),
carousel: renderService.renderCarousel.bind(renderService),
choice: renderService.renderChoice.bind(renderService),
buttonSay: renderService.renderButtonSay.bind(renderService),
buttonUrl: renderService.renderButtonUrl.bind(renderService),
buttonPostback: renderService.renderButtonPostback.bind(renderService),
option: renderService.renderOption.bind(renderService),
translate: renderService.renderTranslated.bind(renderService),
template: renderService.renderTemplate.bind(renderService),
pipeline: renderService.getPipeline.bind(renderService)
}
}

/**
* Socket.IO API to emit payloads to front-end clients
*/
Expand Down Expand Up @@ -288,7 +308,8 @@ export class BotpressAPIProvider {
@inject(TYPES.JobService) jobService: JobService,
@inject(TYPES.StateManager) stateManager: StateManager,
@inject(TYPES.ConversationService) conversationService: ConversationService,
@inject(TYPES.MessageService) messageService: MessageService
@inject(TYPES.MessageService) messageService: MessageService,
@inject(TYPES.RenderService) renderService: RenderService
) {
this.http = http(httpServer)
this.events = event(eventEngine, eventRepo)
Expand All @@ -303,7 +324,7 @@ export class BotpressAPIProvider {
this.ghost = ghost(ghostService)
this.cms = cms(cmsService, mediaServiceProvider)
this.mlToolkit = MLToolkit
this.experimental = experimental(hookService, conversationService, messageService)
this.experimental = experimental(hookService, conversationService, messageService, renderService)
this.security = security()
this.workspaces = workspaces(workspaceService)
this.distributed = distributed(jobService)
Expand Down
3 changes: 3 additions & 0 deletions src/bp/core/botpress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,9 @@ export class Botpress {
await this.hookService.executeHook(new Hooks.BeforeOutgoingMiddleware(this.api, event))
}

// Todo : remove this when channel renderers for builtin types are no longer needed
this.eventEngine.renderForChannel = this.cmsService.renderForChannel.bind(this.cmsService)

this.decisionEngine.onBeforeSuggestionsElection = async (
sessionId: string,
event: sdk.IO.IncomingEvent,
Expand Down
10 changes: 10 additions & 0 deletions src/bp/core/events/event-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ export class EventEngine {

public onBeforeOutgoingMiddleware?: (event: sdk.IO.OutgoingEvent) => Promise<void>

public renderForChannel?: (content: any, channel: string) => any[]

private readonly _incomingPerf = new TimedPerfCounter('mw_incoming')
private readonly _outgoingPerf = new TimedPerfCounter('mw_outgoing')

Expand Down Expand Up @@ -182,6 +184,14 @@ export class EventEngine {
async sendEvent(event: sdk.IO.Event): Promise<void> {
this.validateEvent(event)

// Todo : remove this when per channel rendering is no longer needed for builtin content types
if (event.payload.__unrendered) {
const payloads = this.renderForChannel!(event.payload, event.channel)
const mevent = <any>event
mevent.payload = payloads[payloads.length - 1]
mevent.type = mevent.payload.type
}

if (event.debugger) {
addStepToEvent(event, StepScopes.Received)
this.eventCollector.storeEvent(event)
Expand Down
9 changes: 8 additions & 1 deletion src/bp/core/services/cms.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ContentElement, ContentType, IO, KnexExtended, Logger, SearchParams } from 'botpress/sdk'
import { EventEngine } from 'core/events/event-engine'
import { LoggerProvider } from 'core/logger'
import { renderRecursive, renderTemplate } from 'core/misc/templating'
import { ModuleLoader } from 'core/module-loader'
Expand Down Expand Up @@ -58,7 +59,8 @@ export class CMSService implements IDisposeOnExit {
@inject(TYPES.InMemoryDatabase) private memDb: KnexExtended,
@inject(TYPES.JobService) private jobService: JobService,
@inject(TYPES.MediaServiceProvider) private mediaServiceProvider: MediaServiceProvider,
@inject(TYPES.ModuleLoader) private moduleLoader: ModuleLoader
@inject(TYPES.ModuleLoader) private moduleLoader: ModuleLoader,
@inject(TYPES.EventEngine) private eventEngine: EventEngine
) {}

disposeOnExit() {
Expand Down Expand Up @@ -672,6 +674,11 @@ export class CMSService implements IDisposeOnExit {
return payloads
}

public renderForChannel(content: any, channel: string): any[] {
const type = this.contentTypes.find(x => x.id.includes(content.type))!
return type.renderElement({ ...content, ...this._getAdditionalData() }, channel)
}

/**
* Important! Do not use directly. Needs to be broadcasted.
*/
Expand Down

0 comments on commit 1a6e953

Please sign in to comment.