Skip to content

Commit

Permalink
feat(studio): add support for audio and video content-types (#4816)
Browse files Browse the repository at this point in the history
* feat(studio): add support for audio and video content-types

* add support for file preview

* add warning for audio content-type

* minor ui change

* migration and change default setting

* adjust default in code

* feat(studio): add support for video content-type (#4820)

Co-authored-by: Samuel Massé <samuelmasse4@gmail.com>

* migration for bots

* pr comments

* fix migration

* _merge

* us extension instead of mime-type for filters

* small fix

* pr comments

* remove channel-vonage config schema file

* pr comments

Co-authored-by: Samuel Massé <59894025+samuelmasse@users.noreply.github.com>
Co-authored-by: Samuel Massé <samuelmasse4@gmail.com>
  • Loading branch information
3 people committed Apr 22, 2021
1 parent aaf8873 commit 95ba80d
Show file tree
Hide file tree
Showing 45 changed files with 612 additions and 231 deletions.
90 changes: 90 additions & 0 deletions modules/builtin/src/content-types/audio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const base = require('./_base')
const path = require('path')
const utils = require('./_utils')

function render(data) {
const events = []

if (data.typing) {
events.push({
type: 'typing',
value: data.typing
})
}

return [
...events,
{
type: 'audio',
title: data.title,
url: utils.formatURL(data.BOT_URL, data.audio),
collectFeedback: data.collectFeedback
}
]
}

function renderElement(data, channel) {
// rendering is handled by channel-vonage
if (channel === 'vonage') {
return data
} else {
return render(data)
}
}

module.exports = {
id: 'builtin_audio',
group: 'Built-in Audio',
title: 'Audio',

jsonSchema: {
description: 'module.builtin.types.audio.description',
type: 'object',
$subtype: 'audio',
required: ['audio'],
properties: {
audio: {
type: 'string',
$subtype: 'audio',
$filter: '.mp3',
title: 'module.builtin.types.audio.title'
},
title: {
type: 'string',
title: 'module.builtin.types.audio.audioLabel'
},
...base.typingIndicators
}
},

uiSchema: {
title: {
'ui:field': 'i18n_field'
}
},

computePreviewText: formData => {
if (!formData.audio) {
return
}

const link = utils.formatURL(formData.BOT_URL, formData.audio)
const title = formData.title ? ' | ' + formData.title : ''
let fileName = ''

if (utils.isUrl(link)) {
fileName = path.basename(formData.audio)
if (fileName.includes('-')) {
fileName = fileName
.split('-')
.slice(1)
.join('-')
}
return `Audio: (${fileName}) ${title}`
} else {
return `Expression: ${link}${title}`
}
},

renderElement: renderElement
}
2 changes: 1 addition & 1 deletion modules/builtin/src/content-types/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ module.exports = {
properties: {
image: {
type: 'string',
$subtype: 'media',
$subtype: 'image',
$filter: '.jpg, .png, .jpeg, .gif, .bmp, .tif, .tiff|image/*',
title: 'module.builtin.types.image.title'
},
Expand Down
90 changes: 90 additions & 0 deletions modules/builtin/src/content-types/video.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const base = require('./_base')
const path = require('path')
const utils = require('./_utils')

function render(data) {
const events = []

if (data.typing) {
events.push({
type: 'typing',
value: data.typing
})
}

return [
...events,
{
type: 'video',
title: data.title,
url: utils.formatURL(data.BOT_URL, data.video),
collectFeedback: data.collectFeedback
}
]
}

function renderElement(data, channel) {
// rendering is handled by channel-vonage
if (channel === 'vonage') {
return data
} else {
return render(data)
}
}

module.exports = {
id: 'builtin_video',
group: 'Built-in Video',
title: 'Video',

jsonSchema: {
description: 'module.builtin.types.video.description',
type: 'object',
$subtype: 'video',
required: ['video'],
properties: {
video: {
type: 'string',
$subtype: 'video',
$filter: '.mp4',
title: 'module.builtin.types.video.title'
},
title: {
type: 'string',
title: 'module.builtin.types.video.videoLabel'
},
...base.typingIndicators
}
},

uiSchema: {
title: {
'ui:field': 'i18n_field'
}
},

computePreviewText: formData => {
if (!formData.video) {
return
}

const link = utils.formatURL(formData.BOT_URL, formData.video)
const title = formData.title ? ' | ' + formData.title : ''
let fileName = ''

if (utils.isUrl(link)) {
fileName = path.basename(formData.video)
if (fileName.includes('-')) {
fileName = fileName
.split('-')
.slice(1)
.join('-')
}
return `Video: (${fileName}) ${title}`
} else {
return `Expression: ${link}${title}`
}
},

renderElement: renderElement
}
18 changes: 14 additions & 4 deletions modules/builtin/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"actionButton": "Action Button",
"fullName": "Basic Skills",
"types": {
"permissionDenied": "You don't have permission to upload files for this bot. Talk to your team owner.",
"uploadFileChoice": "Or upload a file",
"enterUrlChoice": "Or enter the URL",
"infoInterpreted": "This information will be interpreted:",
"actionButton": {
"buttonTitle": "Title of the button",
"description": "A button that triggers an action, often used in cards",
Expand All @@ -20,13 +24,19 @@
"description": "A message showing an image with an optional title",
"imageLabel": "Title",
"labelDesc": "Some platforms require to name the images.",
"permissionDenied": "You don't have permission to upload files for this bot. Talk to your team owner.",
"infoInterpreted": "This information will be interpreted:",
"title": "Image",
"uploadFileChoice": "Or upload an image",
"enterUrlChoice": "Or enter the image URL",
"uploadImage": "Upload Image"
},
"audio": {
"description": "A message showing an audio file with an optional title",
"audioLabel": "Title",
"title": "Audio"
},
"video": {
"description": "A message showing a video file with an optional title",
"videoLabel": "Title",
"title": "Video"
},
"singleChoice": {
"choice": "Choice",
"description": "Suggest choices to the user with the intention of picking only one (with an optional message)",
Expand Down
18 changes: 14 additions & 4 deletions modules/builtin/src/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"actionButton": "Botón de Acción",
"fullName": "Habilidades básicas",
"types": {
"permissionDenied": "No tiene permiso para cargar archivos para este bot. Habla con el dueño de tu equipo.",
"uploadFileChoice": "O sube una imagen",
"enterUrlChoice": "O ingrese la URL de la imagen",
"infoInterpreted": "Esta información será interpretada:",
"actionButton": {
"buttonTitle": "Título del botón",
"description": "Un botón que desencadena una acción, a menudo utilizada en tarjetas",
Expand All @@ -20,13 +24,19 @@
"description": "Un mensaje que muestra una imagen con un título opcional.",
"imageLabel": "Título (opcional)",
"labelDesc": "Algunas plataformas requieren nombrar las imágenes.",
"permissionDenied": "You don't have permission to upload files for this bot. Talk to your team owner.",
"infoInterpreted": "Esta información será interpretada:",
"title": "Imagen",
"uploadFileChoice": "O sube una imagen",
"enterUrlChoice": "O ingrese la URL de la imagen",
"uploadImage": "Cargar imagen"
},
"audio": {
"description": "Un mensaje que muestra un archivo de audio con un título opcional.",
"audioLabel": "Título",
"title": "Audio"
},
"video": {
"description": "Un mensaje que muestra un archivo de video con un título opcional",
"videoLabel": "Título",
"title": "Video"
},
"singleChoice": {
"choice": "Elección",
"description": "Sugerir opciones al usuario con la intención de seleccionar solo una (con un mensaje opcional)",
Expand Down
18 changes: 14 additions & 4 deletions modules/builtin/src/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"fullName": "Intégré",
"actionButton": "Bouton d'action",
"types": {
"permissionDenied": "Vous n'avez pas les permissions pour télécharger un fichier pour ce bot. Contactez votre chef d'équipe.",
"uploadFileChoice": "Ou téléchargez un fichier",
"enterUrlChoice": "Ou entrez un URL",
"infoInterpreted": "Cette information sera interprétée:",
"actionButton": {
"buttonTitle": "Titre du bouton",
"description": "Un bouton qui déclenche une action, souvent utilisé dans les cartes",
Expand All @@ -20,13 +24,19 @@
"description": "Un message montrant une image avec un titre optionel",
"imageLabel": "Titre",
"labelDesc": "Certaines plateformes exigent que les images soient nommé.",
"permissionDenied": "Vous n'avez pas les permissions pour télécharger un fichier pour ce bot. Contactez votre chef d'équipe.",
"infoInterpreted": "Cette information sera interprétée:",
"title": "Image",
"uploadFileChoice": "Ou téléchargez une image",
"enterUrlChoice": "Ou entrez l'URL de l'image",
"uploadImage": "Choisir une image"
},
"audio": {
"description": "Un message affichant un fichier audio avec un titre facultatif",
"audioLabel": "Titre",
"title": "Audio"
},
"video": {
"description": "Un message affichant un fichier vidéo avec un titre facultatif",
"videoLabel": "Titre",
"title": "Vidéo"
},
"singleChoice": {
"choice": "Choix",
"description": "Suggérer un choix à l'utilisateur avec l'intention de n'en sélectionner qu'un (avec un message optionnel)",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"@types/jsonwebtoken": "^8.3.7",
"@types/lodash": "^4.14.116",
"@types/lru-cache": "^5.1.0",
"@types/mime-types": "^2.1.0",
"@types/mkdirp": "^1.0.1",
"@types/ms": "^0.7.30",
"@types/mustache": "^0.8.31",
Expand Down
2 changes: 1 addition & 1 deletion src/bp/admin/ui/src/user/UpdateUserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const UpdateUserProfile: FC<Props> = props => {
</FormGroup>

<FormGroup label={lang.tr('admin.profilePicture')}>
<FormFields.Upload axios={v1Client} onChange={uploadFieldChange} value={picture_url} />
<FormFields.Upload axios={v1Client} onChange={uploadFieldChange} value={picture_url} type="image" />
</FormGroup>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/bp/core/config/botpress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,12 @@ export interface BotpressConfig {
fileUpload: {
/**
* Maximum file size for media files upload (in mb)
* @default 10mb
* @default 25mb
*/
maxFileSize: string
/**
* The list of allowed extensions for media file uploads
* @default ["image/jpeg","image/png","image/gif"]
* @default ["image/jpeg","image/png","image/gif","audio/mpeg","video/mp4"]
*/
allowedMimeTypes: string[]
}
Expand Down
2 changes: 1 addition & 1 deletion src/bp/core/media/media-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class MediaRouter extends CustomRouter {
}

private setupPublicRoutes() {
// if the need apprears, add useStream param to which we can stream file straight from media service
// if the need appears, add useStream param to which we can stream file straight from media service
this.router.get(
'/:filename',
this.asyncMiddleware(async (req, res) => {
Expand Down

0 comments on commit 95ba80d

Please sign in to comment.