From 6717e0a1b402f8f38755519758ba05366c31bee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Mass=C3=A9?= <59894025+samuelmasse@users.noreply.github.com> Date: Fri, 28 Jan 2022 21:44:17 -0500 Subject: [PATCH] feat(messenger): messenger v1 (#329) * delete old * use legacy * remove deps * use channels 0.1.0 * bring changes * gif * bring changes * fix * fix * bring changes * rewire comment * fix * start * message reception * fix * send text * refact * readme * image * single-choice * fix * bring changes * bump * fix merge * use channel in server * quick_reply * carousel * refact * fix * audio video location * file * readme --- packages/channels/example/app.ts | 2 + packages/channels/example/payloads.json | 4 +- packages/channels/src/index.ts | 1 + packages/channels/src/messenger/README.md | 29 ++++++ packages/channels/src/messenger/api.ts | 93 +++++++++++++++++++ packages/channels/src/messenger/channel.ts | 28 ++++++ packages/channels/src/messenger/config.ts | 18 ++++ packages/channels/src/messenger/context.ts | 8 ++ packages/channels/src/messenger/messenger.ts | 40 ++++++++ .../channels/src/messenger/renderers/audio.ts | 21 +++++ .../src/messenger/renderers/carousel.ts | 75 +++++++++++++++ .../src/messenger/renderers/choices.ts | 15 +++ .../channels/src/messenger/renderers/file.ts | 9 ++ .../channels/src/messenger/renderers/image.ts | 22 +++++ .../channels/src/messenger/renderers/index.ts | 19 ++++ .../src/messenger/renderers/location.ts | 13 +++ .../channels/src/messenger/renderers/text.ts | 9 ++ .../channels/src/messenger/renderers/video.ts | 21 +++++ .../channels/src/messenger/senders/common.ts | 10 ++ .../channels/src/messenger/senders/index.ts | 4 + .../channels/src/messenger/senders/typing.ts | 12 +++ packages/channels/src/messenger/service.ts | 12 +++ packages/channels/src/messenger/stream.ts | 62 +++++++++++++ .../channels/src/twilio/renderers/file.ts | 2 +- .../channels/src/twilio/renderers/location.ts | 4 +- .../channels/src/twilio/renderers/video.ts | 2 +- packages/server/src/channels/service.ts | 4 +- 27 files changed, 532 insertions(+), 7 deletions(-) create mode 100644 packages/channels/src/messenger/README.md create mode 100644 packages/channels/src/messenger/api.ts create mode 100644 packages/channels/src/messenger/channel.ts create mode 100644 packages/channels/src/messenger/config.ts create mode 100644 packages/channels/src/messenger/context.ts create mode 100644 packages/channels/src/messenger/messenger.ts create mode 100644 packages/channels/src/messenger/renderers/audio.ts create mode 100644 packages/channels/src/messenger/renderers/carousel.ts create mode 100644 packages/channels/src/messenger/renderers/choices.ts create mode 100644 packages/channels/src/messenger/renderers/file.ts create mode 100644 packages/channels/src/messenger/renderers/image.ts create mode 100644 packages/channels/src/messenger/renderers/index.ts create mode 100644 packages/channels/src/messenger/renderers/location.ts create mode 100644 packages/channels/src/messenger/renderers/text.ts create mode 100644 packages/channels/src/messenger/renderers/video.ts create mode 100644 packages/channels/src/messenger/senders/common.ts create mode 100644 packages/channels/src/messenger/senders/index.ts create mode 100644 packages/channels/src/messenger/senders/typing.ts create mode 100644 packages/channels/src/messenger/service.ts create mode 100644 packages/channels/src/messenger/stream.ts diff --git a/packages/channels/example/app.ts b/packages/channels/example/app.ts index 55b75760a..c017f2c17 100644 --- a/packages/channels/example/app.ts +++ b/packages/channels/example/app.ts @@ -2,6 +2,7 @@ import clc from 'cli-color' import { Router } from 'express' import Joi from 'joi' import { Channel } from '../src/base/channel' +import { MessengerChannel } from '../src/messenger/channel' import { TelegramChannel } from '../src/telegram/channel' import { TwilioChannel } from '../src/twilio/channel' import payloads from './payloads.json' @@ -10,6 +11,7 @@ export class App { constructor(private router: Router, private config: any) {} async setup() { + await this.setupChannel('messenger', new MessengerChannel()) await this.setupChannel('twilio', new TwilioChannel()) await this.setupChannel('telegram', new TelegramChannel()) } diff --git a/packages/channels/example/payloads.json b/packages/channels/example/payloads.json index adca04b2c..4ad773cc8 100644 --- a/packages/channels/example/payloads.json +++ b/packages/channels/example/payloads.json @@ -88,8 +88,8 @@ }, { "type": "file", - "title": "here is a zip of the 1.0.0 messaging codebase", - "file": "https://github.com/botpress/messaging/archive/refs/tags/v1.0.0.zip", + "title": "here is a zip of the 0.0.1 messaging codebase", + "file": "https://github.com/botpress/messaging/archive/refs/tags/v0.0.1.zip", "typing": true }, { diff --git a/packages/channels/src/index.ts b/packages/channels/src/index.ts index a55aee4e5..fcbf45501 100644 --- a/packages/channels/src/index.ts +++ b/packages/channels/src/index.ts @@ -1,4 +1,5 @@ export * from './base/channel' export * from './base/endpoint' +export * from './messenger/channel' export * from './twilio/channel' export * from './telegram/channel' diff --git a/packages/channels/src/messenger/README.md b/packages/channels/src/messenger/README.md new file mode 100644 index 000000000..e3ae107b3 --- /dev/null +++ b/packages/channels/src/messenger/README.md @@ -0,0 +1,29 @@ +### Sending + +| Channels | Twilio | +| -------- | :----: | +| Text | ✅ | +| Image | ✅ | +| Choice | ✅ | +| Dropdown | ✅ | +| Card | ✅ | +| Carousel | ✅ | +| File | ✅ | +| Audio | ✅ | +| Video | ✅ | +| Location | ✅ | + +### Receiving + +| Channels | Twilio | +| ------------- | :----: | +| Text | ✅ | +| Quick Reply | ✅ | +| Postback | ✅ | +| Say Something | ✅ | +| Voice | ❌ | +| Image | ❌ | +| File | ❌ | +| Audio | ❌ | +| Video | ❌ | +| Location | ❌ | diff --git a/packages/channels/src/messenger/api.ts b/packages/channels/src/messenger/api.ts new file mode 100644 index 000000000..5b8ec3e85 --- /dev/null +++ b/packages/channels/src/messenger/api.ts @@ -0,0 +1,93 @@ +import crypto from 'crypto' +import express, { Response, Request, NextFunction } from 'express' +import { IncomingMessage } from 'http' +import { ChannelApi, ChannelApiManager, ChannelApiRequest } from '../base/api' +import { MessengerMessage, MessengerPayload } from './messenger' +import { POSTBACK_PREFIX, SAY_PREFIX } from './renderers/carousel' +import { MessengerService } from './service' + +export class MessengerApi extends ChannelApi { + async setup(router: ChannelApiManager) { + router.use('/messenger', express.json({ verify: this.prepareAuth.bind(this) })) + router.get('/messenger', this.handleWebhookVerification.bind(this)) + + router.post('/messenger', this.auth.bind(this)) + router.post('/messenger', this.handleMessageRequest.bind(this)) + } + + private prepareAuth(_req: IncomingMessage, res: Response, buffer: Buffer, _encoding: string) { + res.locals.authBuffer = Buffer.from(buffer) + } + + private async handleWebhookVerification(req: ChannelApiRequest, res: Response) { + const { config } = this.service.get(req.scope) + + const mode = req.query['hub.mode'] + const token = req.query['hub.verify_token'] + const challenge = req.query['hub.challenge'] + + if (mode === 'subscribe' && token === config.verifyToken) { + res.status(200).send(challenge) + } else { + res.sendStatus(403) + } + } + + private async auth(req: Request, res: Response, next: NextFunction) { + const signature = req.headers['x-hub-signature'] as string + const [, hash] = signature.split('=') + + const { config } = this.service.get(req.params.scope) + const expectedHash = crypto.createHmac('sha1', config.appSecret).update(res.locals.authBuffer).digest('hex') + + if (hash !== expectedHash) { + return res.sendStatus(403) + } else { + next() + } + } + + private async handleMessageRequest(req: ChannelApiRequest, res: Response) { + const payload = req.body as MessengerPayload + + for (const { messaging } of payload.entry) { + for (const message of messaging) { + await this.receive(req.scope, message) + } + } + + res.status(200).send('EVENT_RECEIVED') + } + + private async receive(scope: string, message: MessengerMessage) { + if (message.message) { + if (message.message?.quick_reply?.payload) { + await this.service.receive(scope, this.extractEndpoint(message), { + type: 'quick_reply', + text: message.message.text, + payload: message.message.quick_reply.payload + }) + } else { + await this.service.receive(scope, this.extractEndpoint(message), { type: 'text', text: message.message.text }) + } + } else if (message.postback) { + const payload = message.postback.payload + + if (payload.startsWith(SAY_PREFIX)) { + await this.service.receive(scope, this.extractEndpoint(message), { + type: 'say_something', + text: payload.replace(SAY_PREFIX, '') + }) + } else if (payload.startsWith(POSTBACK_PREFIX)) { + await this.service.receive(scope, this.extractEndpoint(message), { + type: 'postback', + payload: payload.replace(POSTBACK_PREFIX, '') + }) + } + } + } + + private extractEndpoint(message: MessengerMessage) { + return { identity: '*', sender: message.sender.id, thread: '*' } + } +} diff --git a/packages/channels/src/messenger/channel.ts b/packages/channels/src/messenger/channel.ts new file mode 100644 index 000000000..2cd72b8a2 --- /dev/null +++ b/packages/channels/src/messenger/channel.ts @@ -0,0 +1,28 @@ +import { ChannelTemplate } from '../base/channel' +import { MessengerApi } from './api' +import { MessengerConfig, MessengerConfigSchema } from './config' +import { MessengerService } from './service' +import { MessengerStream } from './stream' + +export class MessengerChannel extends ChannelTemplate< + MessengerConfig, + MessengerService, + MessengerApi, + MessengerStream +> { + get meta() { + return { + id: 'aa88f73d-a9fb-456f-b0d0-5c0031e4aa34', + name: 'messenger', + version: '1.0.0', + schema: MessengerConfigSchema, + initiable: true, + lazy: true + } + } + + constructor() { + const service = new MessengerService() + super(service, new MessengerApi(service), new MessengerStream(service)) + } +} diff --git a/packages/channels/src/messenger/config.ts b/packages/channels/src/messenger/config.ts new file mode 100644 index 000000000..47fc1c414 --- /dev/null +++ b/packages/channels/src/messenger/config.ts @@ -0,0 +1,18 @@ +import Joi from 'joi' +import { ChannelConfig } from '../base/config' + +export interface MessengerConfig extends ChannelConfig { + appId: string + appSecret: string + verifyToken: string + pageId: string + accessToken: string +} + +export const MessengerConfigSchema = { + appId: Joi.string().required(), + appSecret: Joi.string().required(), + verifyToken: Joi.string().required(), + pageId: Joi.string().required(), + accessToken: Joi.string().required() +} diff --git a/packages/channels/src/messenger/context.ts b/packages/channels/src/messenger/context.ts new file mode 100644 index 000000000..43eacb5da --- /dev/null +++ b/packages/channels/src/messenger/context.ts @@ -0,0 +1,8 @@ +import { ChannelContext } from '../base/context' +import { MessengerState } from './service' +import { MessengerStream } from './stream' + +export type MessengerContext = ChannelContext & { + messages: any[] + stream: MessengerStream +} diff --git a/packages/channels/src/messenger/messenger.ts b/packages/channels/src/messenger/messenger.ts new file mode 100644 index 000000000..3ac60ddb0 --- /dev/null +++ b/packages/channels/src/messenger/messenger.ts @@ -0,0 +1,40 @@ +export interface MessengerPayload { + object: string + entry: MessengerEntry[] +} + +export interface MessengerEntry { + id: string + time: number + messaging: MessengerMessage[] +} + +export interface MessengerMessage { + sender: { id: string } + recipient: { id: string } + timestamp: number + message?: { + mid: string + text: string + quick_reply?: { payload: string } + } + postback?: { + mid: string + payload: string + title: string + } +} + +export interface MessengerCard { + title: string + image_url?: string + subtitle?: string + buttons: MessengerButton[] +} + +export interface MessengerButton { + type: 'web_url' | 'postback' + title?: string + payload?: string + url?: string +} diff --git a/packages/channels/src/messenger/renderers/audio.ts b/packages/channels/src/messenger/renderers/audio.ts new file mode 100644 index 000000000..2af0593bf --- /dev/null +++ b/packages/channels/src/messenger/renderers/audio.ts @@ -0,0 +1,21 @@ +import { AudioRenderer } from '../../base/renderers/audio' +import { AudioContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerAudioRenderer extends AudioRenderer { + renderAudio(context: MessengerContext, payload: AudioContent) { + context.messages.push({ + attachment: { + type: 'audio', + payload: { + is_reusable: true, + url: payload.audio + } + } + }) + + if (payload.title?.length) { + context.messages.push({ text: payload.title }) + } + } +} diff --git a/packages/channels/src/messenger/renderers/carousel.ts b/packages/channels/src/messenger/renderers/carousel.ts new file mode 100644 index 000000000..50110a5ed --- /dev/null +++ b/packages/channels/src/messenger/renderers/carousel.ts @@ -0,0 +1,75 @@ +import { CarouselContext, CarouselRenderer } from '../../base/renderers/carousel' +import { ActionOpenURL, ActionPostback, ActionSaySomething, CardContent, CarouselContent } from '../../content/types' +import { MessengerContext } from '../context' +import { MessengerButton, MessengerCard } from '../messenger' + +export const POSTBACK_PREFIX = 'postback::' +export const SAY_PREFIX = 'say::' + +type Context = CarouselContext & { + cards: MessengerCard[] + buttons: MessengerButton[] +} + +export class MessengerCarouselRenderer extends CarouselRenderer { + startRender(context: Context, carousel: CarouselContent) { + context.cards = [] + } + + startRenderCard(context: Context, card: CardContent) { + context.buttons = [] + } + + renderButtonUrl(context: Context, button: ActionOpenURL) { + context.buttons.push({ + type: 'web_url', + url: button.url, + title: button.title + }) + } + + renderButtonPostback(context: Context, button: ActionPostback) { + context.buttons.push({ + type: 'postback', + title: button.title, + payload: `${POSTBACK_PREFIX}${button.payload}` + }) + } + + renderButtonSay(context: Context, button: ActionSaySomething) { + context.buttons.push({ + type: 'postback', + title: button.title, + payload: `${SAY_PREFIX}${button.text}` + }) + } + + endRenderCard(context: Context, card: CardContent) { + if (context.buttons.length === 0) { + context.buttons.push({ + type: 'postback', + title: card.title, + payload: card.title + }) + } + + context.cards.push({ + title: card.title, + image_url: card.image ? card.image : undefined, + subtitle: card.subtitle, + buttons: context.buttons + }) + } + + endRender(context: Context, carousel: CarouselContent) { + context.channel.messages.push({ + attachment: { + type: 'template', + payload: { + template_type: 'generic', + elements: context.cards + } + } + }) + } +} diff --git a/packages/channels/src/messenger/renderers/choices.ts b/packages/channels/src/messenger/renderers/choices.ts new file mode 100644 index 000000000..5e543d814 --- /dev/null +++ b/packages/channels/src/messenger/renderers/choices.ts @@ -0,0 +1,15 @@ +import { ChoicesRenderer } from '../../base/renderers/choices' +import { ChoiceContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerChoicesRenderer extends ChoicesRenderer { + renderChoice(context: MessengerContext, payload: ChoiceContent): void { + const message = context.messages[0] + + message.quick_replies = payload.choices.map((c) => ({ + content_type: 'text', + title: c.title, + payload: c.value + })) + } +} diff --git a/packages/channels/src/messenger/renderers/file.ts b/packages/channels/src/messenger/renderers/file.ts new file mode 100644 index 000000000..2bc912834 --- /dev/null +++ b/packages/channels/src/messenger/renderers/file.ts @@ -0,0 +1,9 @@ +import { FileRenderer } from '../../base/renderers/file' +import { FileContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerFileRenderer extends FileRenderer { + renderFile(context: MessengerContext, payload: FileContent) { + context.messages.push({ text: `${payload.title ? `${payload.title}\n` : payload.title}${payload.file}` }) + } +} diff --git a/packages/channels/src/messenger/renderers/image.ts b/packages/channels/src/messenger/renderers/image.ts new file mode 100644 index 000000000..781e422ea --- /dev/null +++ b/packages/channels/src/messenger/renderers/image.ts @@ -0,0 +1,22 @@ +import { ImageRenderer } from '../../base/renderers/image' +import { ImageContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerImageRenderer extends ImageRenderer { + renderImage(context: MessengerContext, payload: ImageContent): void { + context.messages.push({ + attachment: { + type: 'image', + payload: { + is_reusable: true, + url: payload.image + } + } + }) + + if (payload.title?.length) { + // TODO: could maybe use the media templat instead? + context.messages.push({ text: payload.title }) + } + } +} diff --git a/packages/channels/src/messenger/renderers/index.ts b/packages/channels/src/messenger/renderers/index.ts new file mode 100644 index 000000000..a7640c7b9 --- /dev/null +++ b/packages/channels/src/messenger/renderers/index.ts @@ -0,0 +1,19 @@ +import { MessengerAudioRenderer } from './audio' +import { MessengerCarouselRenderer } from './carousel' +import { MessengerChoicesRenderer } from './choices' +import { MessengerFileRenderer } from './file' +import { MessengerImageRenderer } from './image' +import { MessengerLocationRenderer } from './location' +import { MessengerTextRenderer } from './text' +import { MessengerVideoRenderer } from './video' + +export const MessengerRenderers = [ + new MessengerTextRenderer(), + new MessengerImageRenderer(), + new MessengerCarouselRenderer(), + new MessengerChoicesRenderer(), + new MessengerFileRenderer(), + new MessengerAudioRenderer(), + new MessengerVideoRenderer(), + new MessengerLocationRenderer() +] diff --git a/packages/channels/src/messenger/renderers/location.ts b/packages/channels/src/messenger/renderers/location.ts new file mode 100644 index 000000000..72789b76f --- /dev/null +++ b/packages/channels/src/messenger/renderers/location.ts @@ -0,0 +1,13 @@ +import { LocationRenderer } from '../../base/renderers/location' +import { LocationContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerLocationRenderer extends LocationRenderer { + renderLocation(context: MessengerContext, payload: LocationContent) { + const googleMapsLink = `https://www.google.com/maps/search/?api=1&query=${payload.latitude},${payload.longitude}` + + context.messages.push({ + text: `${payload.title}${payload.address ? `\n${payload.address}` : ''}\n${googleMapsLink}` + }) + } +} diff --git a/packages/channels/src/messenger/renderers/text.ts b/packages/channels/src/messenger/renderers/text.ts new file mode 100644 index 000000000..f08e34f65 --- /dev/null +++ b/packages/channels/src/messenger/renderers/text.ts @@ -0,0 +1,9 @@ +import { TextRenderer } from '../../base/renderers/text' +import { TextContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerTextRenderer extends TextRenderer { + renderText(context: MessengerContext, payload: TextContent): void { + context.messages.push({ text: payload.text }) + } +} diff --git a/packages/channels/src/messenger/renderers/video.ts b/packages/channels/src/messenger/renderers/video.ts new file mode 100644 index 000000000..fde8bea99 --- /dev/null +++ b/packages/channels/src/messenger/renderers/video.ts @@ -0,0 +1,21 @@ +import { VideoRenderer } from '../../base/renderers/video' +import { VideoContent } from '../../content/types' +import { MessengerContext } from '../context' + +export class MessengerVideoRenderer extends VideoRenderer { + renderVideo(context: MessengerContext, payload: VideoContent) { + context.messages.push({ + attachment: { + type: 'video', + payload: { + is_reusable: true, + url: payload.video + } + } + }) + + if (payload.title?.length) { + context.messages.push({ text: payload.title }) + } + } +} diff --git a/packages/channels/src/messenger/senders/common.ts b/packages/channels/src/messenger/senders/common.ts new file mode 100644 index 000000000..9e71283c7 --- /dev/null +++ b/packages/channels/src/messenger/senders/common.ts @@ -0,0 +1,10 @@ +import { CommonSender } from '../../base/senders/common' +import { MessengerContext } from '../context' + +export class MessengerCommonSender extends CommonSender { + async send(context: MessengerContext) { + for (const message of context.messages) { + await context.stream.sendMessage(context.scope, context, message) + } + } +} diff --git a/packages/channels/src/messenger/senders/index.ts b/packages/channels/src/messenger/senders/index.ts new file mode 100644 index 000000000..0c758fbaa --- /dev/null +++ b/packages/channels/src/messenger/senders/index.ts @@ -0,0 +1,4 @@ +import { MessengerCommonSender } from './common' +import { MessengerTypingSender } from './typing' + +export const MessengerSenders = [new MessengerTypingSender(), new MessengerCommonSender()] diff --git a/packages/channels/src/messenger/senders/typing.ts b/packages/channels/src/messenger/senders/typing.ts new file mode 100644 index 000000000..63003c75d --- /dev/null +++ b/packages/channels/src/messenger/senders/typing.ts @@ -0,0 +1,12 @@ +import { TypingSender } from '../../base/senders/typing' +import { MessengerContext } from '../context' + +export class MessengerTypingSender extends TypingSender { + async sendIndicator(context: MessengerContext) { + await context.stream.sendAction(context.scope, context, 'typing_on') + } + + async stopIndicator(context: MessengerContext) { + await context.stream.sendAction(context.scope, context, 'typing_off') + } +} diff --git a/packages/channels/src/messenger/service.ts b/packages/channels/src/messenger/service.ts new file mode 100644 index 000000000..13004153c --- /dev/null +++ b/packages/channels/src/messenger/service.ts @@ -0,0 +1,12 @@ +import { ChannelService, ChannelState } from '../base/service' +import { MessengerConfig } from './config' + +export interface MessengerState extends ChannelState {} + +export class MessengerService extends ChannelService { + async create(scope: string, config: MessengerConfig) { + return { + config + } + } +} diff --git a/packages/channels/src/messenger/stream.ts b/packages/channels/src/messenger/stream.ts new file mode 100644 index 000000000..49337c458 --- /dev/null +++ b/packages/channels/src/messenger/stream.ts @@ -0,0 +1,62 @@ +import axios from 'axios' +import { Endpoint } from '..' +import { ChannelContext } from '../base/context' +import { CardToCarouselRenderer } from '../base/renderers/card' +import { DropdownToChoicesRenderer } from '../base/renderers/dropdown' +import { ChannelReceiveEvent } from '../base/service' +import { ChannelStream } from '../base/stream' +import { MessengerContext } from './context' +import { MessengerRenderers } from './renderers' +import { MessengerSenders } from './senders' +import { MessengerService } from './service' + +export class MessengerStream extends ChannelStream { + get renderers() { + return [new CardToCarouselRenderer(), new DropdownToChoicesRenderer(), ...MessengerRenderers] + } + + get senders() { + return MessengerSenders + } + + async setup() { + await super.setup() + + this.service.on('receive', this.handleReceive.bind(this)) + } + + protected async handleReceive({ scope, endpoint }: ChannelReceiveEvent) { + await this.sendAction(scope, endpoint, 'mark_seen') + } + + public async sendMessage(scope: string, endpoint: Endpoint, message: any) { + await this.post(scope, endpoint, { message }) + } + + public async sendAction(scope: string, endpoint: Endpoint, action: string) { + await this.post(scope, endpoint, { sender_action: action }) + } + + private async post(scope: string, endpoint: Endpoint, data: any) { + const { config } = this.service.get(scope) + + await axios.post( + 'https://graph.facebook.com/v12.0/me/messages', + { + ...data, + recipient: { + id: endpoint.sender + } + }, + { params: { access_token: config.accessToken } } + ) + } + + protected async getContext(base: ChannelContext): Promise { + return { + ...base, + messages: [], + stream: this + } + } +} diff --git a/packages/channels/src/twilio/renderers/file.ts b/packages/channels/src/twilio/renderers/file.ts index 1b42931c8..db57f3c57 100644 --- a/packages/channels/src/twilio/renderers/file.ts +++ b/packages/channels/src/twilio/renderers/file.ts @@ -4,6 +4,6 @@ import { TwilioContext } from '../context' export class TwilioFileRenderer extends FileRenderer { renderFile(context: TwilioContext, payload: FileContent) { - context.messages.push({ body: `${payload.title}\n\n${payload.file}` }) + context.messages.push({ body: `${payload.title ? `${payload.title}\n` : payload.title}${payload.file}` }) } } diff --git a/packages/channels/src/twilio/renderers/location.ts b/packages/channels/src/twilio/renderers/location.ts index 5c1c78984..69fd5853c 100644 --- a/packages/channels/src/twilio/renderers/location.ts +++ b/packages/channels/src/twilio/renderers/location.ts @@ -6,6 +6,8 @@ export class TwilioLocationRenderer extends LocationRenderer { renderLocation(context: TwilioContext, payload: LocationContent) { const googleMapsLink = `https://www.google.com/maps/search/?api=1&query=${payload.latitude},${payload.longitude}` - context.messages.push({ body: `${payload.title}\n\n${googleMapsLink}` }) + context.messages.push({ + body: `${payload.title}${payload.address ? `\n${payload.address}` : ''}\n${googleMapsLink}` + }) } } diff --git a/packages/channels/src/twilio/renderers/video.ts b/packages/channels/src/twilio/renderers/video.ts index 01e3a453b..acea0403d 100644 --- a/packages/channels/src/twilio/renderers/video.ts +++ b/packages/channels/src/twilio/renderers/video.ts @@ -4,6 +4,6 @@ import { TwilioContext } from '../context' export class TwilioVideoRenderer extends VideoRenderer { renderVideo(context: TwilioContext, payload: VideoContent) { - context.messages.push({ body: `${payload.title}\n\n${payload.video}` }) + context.messages.push({ body: `${payload.title ? `${payload.title}\n` : payload.title}${payload.video}` }) } } diff --git a/packages/server/src/channels/service.ts b/packages/server/src/channels/service.ts index caf9cf30c..e0778508c 100644 --- a/packages/server/src/channels/service.ts +++ b/packages/server/src/channels/service.ts @@ -1,5 +1,5 @@ import { uuid } from '@botpress/messaging-base' -import { Channel, TelegramChannel, TwilioChannel } from '@botpress/messaging-channels' +import { Channel, MessengerChannel, TelegramChannel, TwilioChannel } from '@botpress/messaging-channels' import { MessengerChannel as MessengerChannelLegacy, SlackChannel as SlackChannelLegacy, @@ -30,7 +30,7 @@ export class ChannelService extends Service { this.channels = [] if (yn(process.env.ENABLE_EXPERIMENTAL_CHANNELS)) { - this.channels = [...this.channels, new TelegramChannel(), new TwilioChannel()] + this.channels = [...this.channels, new MessengerChannel(), new TelegramChannel(), new TwilioChannel()] } if (!yn(process.env.DISABLE_LEGACY_CHANNELS)) {