diff --git a/.env b/.env new file mode 100644 index 00000000..a2ce2b2c --- /dev/null +++ b/.env @@ -0,0 +1 @@ +PUBLIC_URL=https://tdurnford.github.io/BotFramework-Offline-MockBot/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d552829f..f05e0492 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3086,6 +3086,12 @@ "domelementtype": "1" } }, + "dotenv": { + "version": "8.1.0", + "resolved": "https://botbuilder.myget.org/F/botbuilder-tools-daily/npm/dotenv/-/dotenv-8.1.0.tgz", + "integrity": "sha1-2BHheGUr+4oeWTxt1wTsfpDYXqI=", + "dev": true + }, "duplexify": { "version": "3.7.1", "resolved": "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/duplexify/-/duplexify-3.7.1.tgz", @@ -3198,7 +3204,7 @@ }, "encoding": { "version": "0.1.12", - "resolved": "https://botbuilder.myget.org/F/botbuilder-tools-daily/npm/encoding/-/encoding-0.1.12.tgz", + "resolved": "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "requires": { "iconv-lite": "~0.4.13" diff --git a/package.json b/package.json index 76bdc567..28f3df89 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "copy-webpack-plugin": "^5.0.3", "core-js": "^3.1.4", "css-loader": "^3.0.0", + "dotenv": "^8.1.0", "eslint": "^6.0.1", "eslint-config-standard": "^13.0.1", "eslint-plugin-import": "^2.18.0", diff --git a/src/Adapter/index.ts b/src/Adapter/index.ts index 41245266..4b5550b4 100644 --- a/src/Adapter/index.ts +++ b/src/Adapter/index.ts @@ -6,7 +6,7 @@ import Observable from 'core-js/features/observable'; import MockBot from '../MockBot'; -export const USER_PROFILE = { id: 'user', name: 'user', role: 'user' }; +export const USER_PROFILE = { id: 'user', role: 'user' }; export const BOT_PROFILE = { id: 'bot', name: 'bot', role: 'bot' }; /** @@ -37,7 +37,6 @@ export default class WebChatAdapter extends BotAdapter { id, conversation: { id: 'bot' }, channelId: 'webchat', - from: USER_PROFILE, recipient: BOT_PROFILE, timestamp }; @@ -114,13 +113,13 @@ export default class WebChatAdapter extends BotAdapter { } export const createDirectLine = ({ processor } = {}) => { - const memory = new MemoryStorage(); - const conversationState = new ConversationState(memory); - const userState = new UserState(memory); - const mockBotAdapter = new WebChatAdapter(); if (!processor) { + const memory = new MemoryStorage(); + const conversationState = new ConversationState(memory); + const userState = new UserState(memory); + const mockBot = new MockBot({ conversationState, userState }); mockBotAdapter.processActivity(async (context) => { diff --git a/src/MockBot/commands/Accessibility.ts b/src/MockBot/commands/Accessibility.ts index a73510cb..11013cc2 100644 --- a/src/MockBot/commands/Accessibility.ts +++ b/src/MockBot/commands/Accessibility.ts @@ -21,7 +21,7 @@ async function processor(context: TurnContext) { await DocumentWord.processor(context); await Image.processor(context); await ImageSVG.processor(context); - await Layout.processor(context); + await Layout.processor(context, { args: '' }); await Layout.processor(context, { args: 'single' }); await Layout.processor(context, { args: 'single carousel' }); await Layout.processor(context, { args: 'double' }); diff --git a/src/MockBot/commands/AdaptiveCard.ts b/src/MockBot/commands/AdaptiveCard.ts index 6247bf29..5e7a05cd 100644 --- a/src/MockBot/commands/AdaptiveCard.ts +++ b/src/MockBot/commands/AdaptiveCard.ts @@ -106,7 +106,7 @@ const processor = async (context: TurnContext, { args }: { args: string }) => { const contents = names.filter(name => name).map(name => getCardJSON(name)); if (contents && contents.length) { - let text = `Showing ${ names.filter(name => name).join(', ') }`; + let text = `Showing ${ names.filter(name => name).join(', ') }`; await context.sendActivity({ type: 'message', diff --git a/src/MockBot/commands/AnimationCard.ts b/src/MockBot/commands/AnimationCard.ts index d5759f3d..ffc6268b 100644 --- a/src/MockBot/commands/AnimationCard.ts +++ b/src/MockBot/commands/AnimationCard.ts @@ -5,6 +5,7 @@ const help = () => ({ }); const processor = async (context: TurnContext) => { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', @@ -16,7 +17,7 @@ const processor = async (context: TurnContext) => { text: 'No buttons, No Image, Autoloop, Autostart, Sharable', media: [{ profile: 'animation', - url: `./assets/surface_anim.gif`, + url: `${PUBLIC_URL}assets/surface_anim.gif`, }], autoloop: true, autostart: true diff --git a/src/MockBot/commands/Audio.ts b/src/MockBot/commands/Audio.ts index 77dd333d..9a52b986 100644 --- a/src/MockBot/commands/Audio.ts +++ b/src/MockBot/commands/Audio.ts @@ -5,14 +5,14 @@ const help = () => ({ }); const processor = async (context: TurnContext) => { - + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', text: '', attachments: [{ contentType: 'audio/mpeg', - contentUrl: `./assets/bftest.mp3`, + contentUrl: `${PUBLIC_URL}assets/bftest.mp3`, name: 'BotFramework Test' }] }); diff --git a/src/MockBot/commands/Cards/Inputs.ts b/src/MockBot/commands/Cards/Inputs.ts index 0c2009fc..aa078631 100644 --- a/src/MockBot/commands/Cards/Inputs.ts +++ b/src/MockBot/commands/Cards/Inputs.ts @@ -127,7 +127,8 @@ export default () => ({ "value": "3" } ], - "id": "CompactSelectVal" + "id": "CompactSelectVal", + "style": "expanded" }, { "type": "TextBlock", diff --git a/src/MockBot/commands/Carousel.ts b/src/MockBot/commands/Carousel.ts index 8b5fd544..e05e511c 100644 --- a/src/MockBot/commands/Carousel.ts +++ b/src/MockBot/commands/Carousel.ts @@ -5,6 +5,7 @@ const help = () => ({ }); const processor = async (context: TurnContext) => { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', @@ -17,7 +18,7 @@ const processor = async (context: TurnContext) => { subtitle: 'This is the subtitle', text: 'Price: $XXX.XX USD', images: [{ - url: `./assets/surface1.jpg` + url: `${PUBLIC_URL}assets/surface1.jpg` }], buttons: [{ type: 'imBack', @@ -36,7 +37,7 @@ const processor = async (context: TurnContext) => { subtitle: 'This is the subtitle', text: 'Price: $XXX.XX USD', images: [{ - url: `./assets/surface2.jpg` + url: `${PUBLIC_URL}assets/surface2.jpg` }], buttons: [{ type: 'imBack', @@ -55,7 +56,7 @@ const processor = async (context: TurnContext) => { subtitle: 'This is the subtitle', text: 'Price: $XXX.XX USD', images: [{ - url: `./assets/surface3.jpg` + url: `${PUBLIC_URL}assets/surface3.jpg` }], buttons: [{ type: 'imBack', @@ -74,7 +75,7 @@ const processor = async (context: TurnContext) => { subtitle: 'This is the subtitle', text: 'Price: $XXX.XX USD', images: [{ - url: `./assets/surface4.jpg` + url: `${PUBLIC_URL}assets/surface4.jpg` }], buttons: [{ type: 'imBack', diff --git a/src/MockBot/commands/Default.ts b/src/MockBot/commands/Default.ts index aeac32e7..4ea4c62b 100644 --- a/src/MockBot/commands/Default.ts +++ b/src/MockBot/commands/Default.ts @@ -2,9 +2,10 @@ import { TurnContext } from 'botbuilder-core'; const processor = async (context: TurnContext) => { const { activity: { text }} = context; + const unknown = text.replace(/\.$/, ''); await context.sendActivity({ - speak: `Unknown command: I don't know ${ text }. You can say "help" to learn more.`, - text: `Unknown command: \`${ text }\`.\r\n\r\nType \`help\` to learn more.`, + speak: `Unknown command: I don't know ${ unknown }. You can say "help" to learn more.`, + text: `Unknown command: \`${ unknown }\`.\r\n\r\nType \`help\` to learn more.`, }); }; diff --git a/src/MockBot/commands/DocumentPlain.ts b/src/MockBot/commands/DocumentPlain.ts index 460e8d5c..cc99c9e8 100644 --- a/src/MockBot/commands/DocumentPlain.ts +++ b/src/MockBot/commands/DocumentPlain.ts @@ -5,12 +5,13 @@ const help = () => ({ }); async function processor(context: TurnContext) { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', attachments: [{ contentType: 'text/plain', - contentUrl: `./assets/test.txt`, + contentUrl: `${PUBLIC_URL}assets/test.txt`, name: 'test.txt' }] }); diff --git a/src/MockBot/commands/DocumentWord.ts b/src/MockBot/commands/DocumentWord.ts index c5c7d9cf..085fc5e7 100644 --- a/src/MockBot/commands/DocumentWord.ts +++ b/src/MockBot/commands/DocumentWord.ts @@ -5,12 +5,13 @@ const help = () => ({ }); async function processor(context: TurnContext) { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', attachments: [{ contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - contentUrl: `./assets/test.docx`, + contentUrl: `${PUBLIC_URL}assets/test.docx`, name: 'test.docx' }] }); diff --git a/src/MockBot/commands/Echo.ts b/src/MockBot/commands/Echo.ts index b318ad68..b0cd5164 100644 --- a/src/MockBot/commands/Echo.ts +++ b/src/MockBot/commands/Echo.ts @@ -6,12 +6,12 @@ const help = () => ({ 'echo "Hello\nWorld!"': 'Parse the message as JSON and echo back' }); -const processor = async (context: TurnContext, { args }) => { +const processor = async (context: TurnContext, { text }) => { - const text = args[0] === '"' ? onErrorResumeNext(() => JSON.parse(args)) || '[Error while parsing the JSON]' : args; + const echo = text[0] === '"' ? onErrorResumeNext(() => JSON.parse(text)) || '[Error while parsing the JSON]' : text; await context.sendActivity('Echoing back in a separate activity.'); - await context.sendActivity(text); + await context.sendActivity(echo); } export default { diff --git a/src/MockBot/commands/File.ts b/src/MockBot/commands/File.ts index ab27b405..d0c290fc 100644 --- a/src/MockBot/commands/File.ts +++ b/src/MockBot/commands/File.ts @@ -5,17 +5,18 @@ const help = () => ({ }); async function processor(context: TurnContext) { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', text: 'The reports are ready, see attached.', attachments: [{ contentType: 'application/octet-stream', - contentUrl: `./assets/test.txt`, + contentUrl: `${PUBLIC_URL}assets/test.txt`, name: 'Plain text' }, { contentType: 'application/octet-stream', - contentUrl: `./assets/test.docx`, + contentUrl: `${PUBLIC_URL}assets/test.docx`, name: 'Word document' }] }); diff --git a/src/MockBot/commands/HeroCard.ts b/src/MockBot/commands/HeroCard.ts index bede2e2a..27683e34 100644 --- a/src/MockBot/commands/HeroCard.ts +++ b/src/MockBot/commands/HeroCard.ts @@ -6,6 +6,7 @@ const help = () => ({ }); const processor = async (context: TurnContext, { args }) => { + const { PUBLIC_URL } = process.env; const heroCard = { contentType: 'application/vnd.microsoft.card.hero', @@ -22,7 +23,7 @@ const processor = async (context: TurnContext, { args }) => { title: 'Tapped it!', value: `https://webchat-mockbot.azurewebsites.net/public/testurl1.html` }, - url: `./assets/surface1.jpg`, + url: `${PUBLIC_URL}assets/surface1.jpg`, }], tap: { type: 'openUrl', @@ -39,6 +40,29 @@ const processor = async (context: TurnContext, { args }) => { heroCard.content.title = 'This is a HeroCard with a really, really long title that is intended to test the richCardsWrapTitle style option.'; } else { heroCard.content.text = '**Price: $XXX.XX USD**\r\n------\n Additional details\r\n1. List item 1 \n2. List item 2 \n3. List item 3'; + heroCard.content.buttons = [ + { + title: 'imBack Action', + type: 'imBack', + value: 'imBack Button' + }, + { + title: 'postBack Action', + type: 'postBack', + value: 'postBack Button' + }, + { + displayText: 'Send messageBack with display text', + title: 'messageBack Action with displayText', + type: 'messageBack', + value: 'messageBack Button' + }, + { + title: 'messageBack Action with no display text', + type: 'messageBack', + value: 'messageBack Button' + }, + ]; } await context.sendActivity({ attachments: [heroCard] }); diff --git a/src/MockBot/commands/Image.ts b/src/MockBot/commands/Image.ts index 93318ace..f53a1cc0 100644 --- a/src/MockBot/commands/Image.ts +++ b/src/MockBot/commands/Image.ts @@ -5,11 +5,12 @@ const help = () => ({ }); const processor = async (context: TurnContext) => { + const { PUBLIC_URL } = process.env; await context.sendActivity({ attachments: [{ contentType: 'image/jpeg', - contentUrl: `./assets/surface1.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg`, name: 'Microsoft Surface' }] }); diff --git a/src/MockBot/commands/ImageSVG.ts b/src/MockBot/commands/ImageSVG.ts index 397fcc11..df3e2726 100644 --- a/src/MockBot/commands/ImageSVG.ts +++ b/src/MockBot/commands/ImageSVG.ts @@ -5,12 +5,13 @@ const help = () => ({ }); async function processor(context: TurnContext) { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', attachments: [{ contentType: 'image/svg+xml', - contentUrl: `./assets/bf_square.svg`, + contentUrl: `${PUBLIC_URL}assets/bf_square.svg`, name: 'Microsoft Bot Framework' }] }); diff --git a/src/MockBot/commands/Hint.ts b/src/MockBot/commands/InputHints.ts similarity index 95% rename from src/MockBot/commands/Hint.ts rename to src/MockBot/commands/InputHints.ts index 8a13d5af..c6db7f74 100644 --- a/src/MockBot/commands/Hint.ts +++ b/src/MockBot/commands/InputHints.ts @@ -56,6 +56,6 @@ async function processor(context: TurnContext, { args }: { args: string; }) { export default { help, name: 'Input hint', - pattern: /^hint(\s+[\d\w]+)?(\s+[\d\w]+)?/i, + pattern: /^input[\-\s]hint(\s+[\d\w]+)?(\s+[\d\w]+)?|^hint(\s+[\d\w]+)?(\s+[\d\w]+)?/i, processor } diff --git a/src/MockBot/commands/Layout.ts b/src/MockBot/commands/Layout.ts index 4661505e..9bd3b96f 100644 --- a/src/MockBot/commands/Layout.ts +++ b/src/MockBot/commands/Layout.ts @@ -8,7 +8,8 @@ const help = () => ({ 'layout': 'Show 4 attachments in stacked layout' }); -async function processor(context: TurnContext, { args }) { +async function processor(context: TurnContext, { args } = {}) { + const { PUBLIC_URL } = process.env; switch (args) { case 'single': @@ -17,7 +18,7 @@ async function processor(context: TurnContext, { args }) { text: 'This command show single attachment in **default (stacked)** layout', attachments: [{ contentType: 'image/jpg', - contentUrl: `./assets/surface1.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg`, name: 'Microsoft Surface' }] }); @@ -32,7 +33,7 @@ async function processor(context: TurnContext, { args }) { attachmentLayout: 'carousel', attachments: [{ contentType: 'image/jpg', - contentUrl: `./assets/surface1.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg`, name: 'Microsoft Surface' }] }); @@ -46,11 +47,11 @@ async function processor(context: TurnContext, { args }) { attachmentLayout: 'carousel', attachments: [{ contentType: 'image/jpg', - contentUrl: `./assets/surface1.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg`, name: 'Microsoft Surface' }, { contentType: 'image/jpg', - contentUrl: `./assets/surface2.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface2.jpg`, name: 'Microsoft Surface' }] }); @@ -64,7 +65,7 @@ async function processor(context: TurnContext, { args }) { attachmentLayout: 'carousel', attachments: [{ contentType: 'image/jpg', - contentUrl: `./assets/surface1.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg`, name: 'Microsoft Surface' }, { contentType: 'text/plain', @@ -86,7 +87,7 @@ async function processor(context: TurnContext, { args }) { text: 'This command show 4 attachments in **default (stacked)** layout', attachments: [{ contentType: 'image/jpg', - contentUrl: `./assets/surface1.jpg`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg`, name: 'Microsoft Surface' }, { contentType: 'text/plain', diff --git a/src/MockBot/commands/MultimediaCard.ts b/src/MockBot/commands/MultimediaCard.ts index e420db7e..172b13cd 100644 --- a/src/MockBot/commands/MultimediaCard.ts +++ b/src/MockBot/commands/MultimediaCard.ts @@ -5,6 +5,7 @@ const help = () => ({ }); async function processor(context: TurnContext) { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', @@ -15,8 +16,8 @@ async function processor(context: TurnContext) { subtitle: 'Subtitle', text: 'Text', media: [ - { url: `./assets/surface_anim.gif`, profile: 'animation' }, - { url: `./assets/surface_anim.gif`, profile: 'animation2' } + { url: `${PUBLIC_URL}assets/surface_anim.gif`, profile: 'animation' }, + { url: `${PUBLIC_URL}assets/surface_anim.gif`, profile: 'animation2' } ], autoloop: true, autostart: true @@ -28,8 +29,8 @@ async function processor(context: TurnContext) { subtitle: 'audio test', text: 'No buttons, No Image, Autoloop, Sharable', media: [ - { url: `./assets/bftest.mp3`, profile: 'audiocard' }, - { url: `./assets/bftest.mp3`, profile: 'audiocard2' } + { url: `${PUBLIC_URL}assets/bftest.mp3`, profile: 'audiocard' }, + { url: `${PUBLIC_URL}assets/bftest.mp3`, profile: 'audiocard2' } ], autoloop: true, autostart: false @@ -41,10 +42,10 @@ async function processor(context: TurnContext) { subtitle: 'Large Video', text: 'No buttons, No Image, Autoloop, No Sharable', media: [ - { url: `./assets/msband.mp4`, profile: 'videocard' }, - { url: `./assets/msband.mp4`, profile: 'videocard2' } + { url: `${PUBLIC_URL}assets/msband.mp4`, profile: 'videocard' }, + { url: `${PUBLIC_URL}assets/msband.mp4`, profile: 'videocard2' } ], - image: { url: `./assets/ms-band1.jpg` }, + image: { url: `${PUBLIC_URL}assets/ms-band1.jpg` }, autoloop: true, autostart: false } diff --git a/src/MockBot/commands/OAuthCard2.ts b/src/MockBot/commands/OAuthCard2.ts index 2a2def57..dbfebb57 100644 --- a/src/MockBot/commands/OAuthCard2.ts +++ b/src/MockBot/commands/OAuthCard2.ts @@ -1,80 +1,80 @@ -import { TurnContext } from 'botbuilder-core'; -import { OAuthPrompt, DialogSet, ChoicePrompt, WaterfallDialog } from 'botbuilder-dialogs'; -import fetch from 'node-fetch'; - -import conversationState from '../singletonConversationState'; - -const dialogState = conversationState['createProperty']('dialogState'); -const dialogs = new DialogSet(dialogState); - -dialogs.add(new ChoicePrompt('CONFIRM_PROMPT')); - -dialogs.add(new OAuthPrompt('OAUTH_PROMPT', { - connectionName: process.env.OAUTH_CONNECTION_NAME, - text: 'Sign into GitHub', - title: 'Sign in' -})); - -dialogs.add(new WaterfallDialog('AUTH_DIALOG', [ - async step => await step.prompt('OAUTH_PROMPT', {}), - async step => { - if (step.result) { - await step.context.sendActivity('You have now logged in.'); - - return await step.next(step.result); - } else { - await step.context.sendActivity('Failed to login, please try again.'); - - return await step.endDialog(); - } - }, - async step => { - await step.context.sendActivity('Please wait while I am bringing up your GitHub profile.'); - - step.context.sendActivity({ type: 'typing' }); - - const { result: { token } } = step; - const res = await fetch(`https://api.github.com/user?access_token=${ encodeURIComponent(token) }`); - - if (res.ok) { - const json = await res.json(); - - await step.context.sendActivity(`![${ json.login }](${ json.avatar_url })\r\n# \`${ json.login }\``); - } else { - await step.context.sendActivity(`Failed to bring up your profile, GitHub server returned \`${ res.status }\`.`); - } - - return await step.endDialog(); - } -])); - -const help = () => ({ - 'oauth': 'Start OAuth flow', - 'oauth signout': 'Sign out' -}); - -async function processor(context: TurnContext, arg?: string) { - if ((arg || '').trim() === 'oauth signout') { - await context.sendActivity('Please wait while I am signing you out.'); - await context.sendActivity({ type: 'typing' }); - await context.adapter['signOutUser'](context, process.env.OAUTH_CONNECTION_NAME); - await context.sendActivity('You have been signed out now.'); - } else { - const dialogContext = await dialogs.createContext(context); - - await dialogContext.continueDialog(); - - if (!context.responded) { - await dialogContext.beginDialog('AUTH_DIALOG'); - } - - await conversationState['saveChanges'](context); - } -} - -export default { - help, - name: 'OAuth card', - pattern: /^(oauth(\s+[\d\w]+)?|\d{6})$/i, - processor - } +// import { TurnContext } from 'botbuilder-core'; +// import { OAuthPrompt, DialogSet, ChoicePrompt, WaterfallDialog } from 'botbuilder-dialogs'; +// import fetch from 'node-fetch'; + +// import conversationState from '../singletonConversationState'; + +// const dialogState = conversationState['createProperty']('dialogState'); +// const dialogs = new DialogSet(dialogState); + +// dialogs.add(new ChoicePrompt('CONFIRM_PROMPT')); + +// dialogs.add(new OAuthPrompt('OAUTH_PROMPT', { +// connectionName: process.env.OAUTH_CONNECTION_NAME, +// text: 'Sign into GitHub', +// title: 'Sign in' +// })); + +// dialogs.add(new WaterfallDialog('AUTH_DIALOG', [ +// async step => await step.prompt('OAUTH_PROMPT', {}), +// async step => { +// if (step.result) { +// await step.context.sendActivity('You have now logged in.'); + +// return await step.next(step.result); +// } else { +// await step.context.sendActivity('Failed to login, please try again.'); + +// return await step.endDialog(); +// } +// }, +// async step => { +// await step.context.sendActivity('Please wait while I am bringing up your GitHub profile.'); + +// step.context.sendActivity({ type: 'typing' }); + +// const { result: { token } } = step; +// const res = await fetch(`https://api.github.com/user?access_token=${ encodeURIComponent(token) }`); + +// if (res.ok) { +// const json = await res.json(); + +// await step.context.sendActivity(`![${ json.login }](${ json.avatar_url })\r\n# \`${ json.login }\``); +// } else { +// await step.context.sendActivity(`Failed to bring up your profile, GitHub server returned \`${ res.status }\`.`); +// } + +// return await step.endDialog(); +// } +// ])); + +// const help = () => ({ +// 'oauth': 'Start OAuth flow', +// 'oauth signout': 'Sign out' +// }); + +// async function processor(context: TurnContext, arg?: string) { +// if ((arg || '').trim() === 'oauth signout') { +// await context.sendActivity('Please wait while I am signing you out.'); +// await context.sendActivity({ type: 'typing' }); +// await context.adapter['signOutUser'](context, process.env.OAUTH_CONNECTION_NAME); +// await context.sendActivity('You have been signed out now.'); +// } else { +// const dialogContext = await dialogs.createContext(context); + +// await dialogContext.continueDialog(); + +// if (!context.responded) { +// await dialogContext.beginDialog('AUTH_DIALOG'); +// } + +// await conversationState['saveChanges'](context); +// } +// } + +// export default { +// help, +// name: 'OAuth card', +// pattern: /^(oauth(\s+[\d\w]+)?|\d{6})$/i, +// processor +// } diff --git a/src/MockBot/commands/ReceiptCard.ts b/src/MockBot/commands/ReceiptCard.ts index e676d675..4efa13ca 100644 --- a/src/MockBot/commands/ReceiptCard.ts +++ b/src/MockBot/commands/ReceiptCard.ts @@ -5,6 +5,7 @@ const help = () => ({ }); const processor = async (context: TurnContext) => { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', @@ -20,7 +21,7 @@ const processor = async (context: TurnContext) => { subtitle: 'Surface Pro 4 is a powerful, versatile, lightweight laptop.', text: 'Surface does more. Just like you. For one device that does everything, you need more than a mobile OS.', image: { - url: `./assets/surface1.jpg`, + url: `${PUBLIC_URL}assets/surface1.jpg`, alt: 'Microsoft Surface Alt', tap: { type: 'openUrl', @@ -32,7 +33,7 @@ const processor = async (context: TurnContext) => { }, { title: 'Surface Pro 4 (2) - No subtitle, No text.', image: { - url: `./assets/surface2.jpg`, + url: `${PUBLIC_URL}assets/surface2.jpg`, alt: 'Microsoft Surface Alt', tap: { type: 'call', diff --git a/src/MockBot/commands/Slow.ts b/src/MockBot/commands/Slow.ts index 5593b20b..f1bc2533 100644 --- a/src/MockBot/commands/Slow.ts +++ b/src/MockBot/commands/Slow.ts @@ -5,18 +5,19 @@ const help = () => ({ }); async function processor(context: TurnContext, { args }) { + const { PUBLIC_URL } = process.env; if (arg === 'markdown') { await context.sendActivity([ 'This Markdown text contains few images with emulated slow network.', '', - `![Photo 1](./assets/surface1.jpg?slow)`, + `![Photo 1](${PUBLIC_URL}assets/surface1.jpg?slow)`, '', - `![Photo 2](./assets/surface2.jpg?slow)`, + `![Photo 2](${PUBLIC_URL}assets/surface2.jpg?slow)`, '', - `![Photo 3](./assets/surface3.jpg?slow)`, + `![Photo 3](${PUBLIC_URL}assets/surface3.jpg?slow)`, '', - `![Photo 4](./assets/surface4.jpg?slow)` + `![Photo 4](${PUBLIC_URL}assets/surface4.jpg?slow)` ].join('\n')); } else { @@ -31,19 +32,19 @@ async function processor(context: TurnContext, { args }) { attachmentLayout: 'carousel', attachments: [{ contentType: 'image/jpg', - contentUrl: `./assets/surface1.jpg?slow`, + contentUrl: `${PUBLIC_URL}assets/surface1.jpg?slow`, name: 'Microsoft Surface Front View' }, { contentType: 'image/jpg', - contentUrl: `./assets/surface2.jpg?slow`, + contentUrl: `${PUBLIC_URL}assets/surface2.jpg?slow`, name: 'Microsoft Surface Back View' }, { contentType: 'image/jpg', - contentUrl: `./assets/surface3.jpg?slow`, + contentUrl: `${PUBLIC_URL}assets/surface3.jpg?slow`, name: 'Microsoft Surface Side Zoom' }, { contentType: 'image/jpg', - contentUrl: `./assets/surface4.jpg?slow`, + contentUrl: `${PUBLIC_URL}assets/surface4.jpg?slow`, name: 'Microsoft Surface Keyboard Zoom' }] }); diff --git a/src/MockBot/commands/SuggestedActionsCard.ts b/src/MockBot/commands/SuggestedActionsCard.ts index fbb1de6b..752c5294 100644 --- a/src/MockBot/commands/SuggestedActionsCard.ts +++ b/src/MockBot/commands/SuggestedActionsCard.ts @@ -7,6 +7,7 @@ const help = () => ({ }); const processor = async (context: TurnContext, { args }) => { + const { PUBLIC_URL } = process.env; if (args === 'others') { // Related to #1057 @@ -34,19 +35,19 @@ const processor = async (context: TurnContext, { args }) => { suggestedActions: { actions: [ { - image: `./assets/square-icon.png`, + image: `${PUBLIC_URL}assets/square-icon.png`, title: 'IM back as string', type: 'imBack', value: 'postback imback-string', }, { - image: `./assets/square-icon-red.png`, + image: `${PUBLIC_URL}assets/square-icon-red.png`, title: 'Post back as string', type: 'postBack', value: 'postback postback-string', }, { - image: `./assets/square-icon-green.png`, + image: `${PUBLIC_URL}assets/square-icon-green.png`, title: 'Post back as JSON', text: 'Some text', type: 'postBack', @@ -55,7 +56,7 @@ const processor = async (context: TurnContext, { args }) => { }, }, { - image: `./assets/square-icon-purple.png`, + image: `${PUBLIC_URL}assets/square-icon-purple.png`, displayText: 'say Hello World!', title: 'Message back as JSON with display text', text: 'Some text', @@ -65,7 +66,7 @@ const processor = async (context: TurnContext, { args }) => { }, }, { - image: `./assets/square-icon-purple.png`, + image: `${PUBLIC_URL}assets/square-icon-purple.png`, title: 'Message back as JSON without display text', type: 'messageBack', value: { @@ -74,7 +75,7 @@ const processor = async (context: TurnContext, { args }) => { }, { displayText: 'Aloha', - image: `./assets/square-icon-purple.png`, + image: `${PUBLIC_URL}assets/square-icon-purple.png`, text: 'echo Hello', title: 'Message back as string with display text', type: 'messageBack', diff --git a/src/MockBot/commands/ThumbnailCard.ts b/src/MockBot/commands/ThumbnailCard.ts index 67956e29..0305bfa9 100644 --- a/src/MockBot/commands/ThumbnailCard.ts +++ b/src/MockBot/commands/ThumbnailCard.ts @@ -6,6 +6,7 @@ const help = () => ({ }); const processor = async (context: TurnContext, { args }) => { + const { PUBLIC_URL } = process.env; const thumbnailCard = { contentType: 'application/vnd.microsoft.card.thumbnail', @@ -13,7 +14,7 @@ const processor = async (context: TurnContext, { args }) => { buttons: [], images: [{ alt: 'Microsoft Surface Alt', - url: `./assets/surface1.jpg`, + url: `${PUBLIC_URL}assets/surface1.jpg`, }], title: 'Microsoft Surface Pro', } diff --git a/src/MockBot/commands/Video.ts b/src/MockBot/commands/Video.ts index 9689c2a1..36038988 100644 --- a/src/MockBot/commands/Video.ts +++ b/src/MockBot/commands/Video.ts @@ -7,6 +7,7 @@ const help = () => ({ }); async function processor(context: TurnContext, { args }: { args: string }) { + const { PUBLIC_URL } = process.env; switch (args) { case 'vimeo': @@ -34,7 +35,7 @@ async function processor(context: TurnContext, { args }: { args: string }) { type: 'message', attachments: [{ contentType: 'video/mp4', - contentUrl: `./assets/msband.mp4`, + contentUrl: `${PUBLIC_URL}assets/msband.mp4`, name: 'Microsoft Band 2' }] }); diff --git a/src/MockBot/commands/VideoCard.ts b/src/MockBot/commands/VideoCard.ts index 1ac71ed1..b1a8158c 100644 --- a/src/MockBot/commands/VideoCard.ts +++ b/src/MockBot/commands/VideoCard.ts @@ -5,6 +5,7 @@ const help = () => ({ }); const processor = async (context: TurnContext) => { + const { PUBLIC_URL } = process.env; await context.sendActivity({ type: 'message', @@ -15,10 +16,10 @@ const processor = async (context: TurnContext) => { subtitle: 'Large Video', text: 'No buttons, No Image, Autoloop, No Sharable', media: [{ - url: `./assets/msband.mp4`, + url: `${PUBLIC_URL}assets/msband.mp4`, profile: 'videocard' }], - image: { url: `./assets/ms-band1.jpg` }, + image: { url: `${PUBLIC_URL}assets/ms-band1.jpg` }, autoloop: true, autostart: false } diff --git a/src/MockBot/commands/index.ts b/src/MockBot/commands/index.ts index a589925a..aa7877b2 100644 --- a/src/MockBot/commands/index.ts +++ b/src/MockBot/commands/index.ts @@ -12,16 +12,18 @@ import EmptyCard from './EmptyCard'; import Help from './Help'; import HelpSimple from './HelpSimple'; import HeroCard from './HeroCard'; -import Hint from './Hint'; +import Hint from './InputHints'; import Image from './Image'; +import Layout from './Layout'; import Markdown from './Markdown'; import ReceiptCard from './ReceiptCard'; import SuggestedActionsCard from './SuggestedActionsCard'; import Text from './Text'; import ThumbnailCard from './ThumbnailCard'; import Typing from './Typing'; -import User from './User'; +import Unknown from './Unknown'; import Upload from './Upload'; +import User from './User'; import Value from './Value'; import Video from './Video'; import VideoCard from './VideoCard'; @@ -43,14 +45,16 @@ export default [ HeroCard, Hint, Image, + Layout, Markdown, ReceiptCard, SuggestedActionsCard, Text, ThumbnailCard, Typing, - User, + Unknown, Upload, + User, Video, VideoCard, Xml @@ -59,4 +63,4 @@ export default [ pattern: typeof command.pattern === 'string' ? new RegExp(`^${ command.pattern }$`, 'i') : command.pattern, })); -export { Default, Value }; +export { Default, Upload, Value }; diff --git a/src/MockBot/index.ts b/src/MockBot/index.ts index 7bdee73a..a52c3397 100644 --- a/src/MockBot/index.ts +++ b/src/MockBot/index.ts @@ -1,5 +1,5 @@ import { ActivityHandler, TurnContext, ActivityTypes } from 'botbuilder-core'; -import commands, { Default, Value } from './commands'; +import commands, { Default, Upload, Value } from './commands'; export default class MockBot extends ActivityHandler { @@ -13,21 +13,22 @@ export default class MockBot extends ActivityHandler { this.echoTypingAccessor = conversationState.createProperty('echoTyping'); this.onMessage(async (context: TurnContext) => { - const { activity: { attachments, text = '', value }} = context; + const { activity: { attachments = [], text = '', value }} = context; const { echoTypingAccessor } = this; - const cleanedText = text.toLowerCase().trim().replace(/\.$/, ''); + const cleanedText = text.trim().replace(/\.$/, ''); const command = commands.find(({ pattern }) => pattern.test(cleanedText)); if (command) { const options = { - args: cleanedText.split(' ').slice(1).join(' '), - echoTypingAccessor + args: cleanedText.toLowerCase().split(' ').slice(1).join(' '), + echoTypingAccessor, + text: cleanedText.split(' ').slice(1).join(' '), }; await command.processor(context, options); - } else if (attachments) { - + } else if (attachments.length) { + await Upload.processor(context); } else if (value) { await Value.processor(context); } else { @@ -38,6 +39,14 @@ export default class MockBot extends ActivityHandler { await this.userState.saveChanges(context); }); + this.onEvent(async (context: TurnContext) => { + if (context.activity.name === 'webchat/join') { + await context.sendActivity(`Got \`webchat/join\` event, your language is \`${ (context.activity.value || {}).language }\``); + } else if (context.activity.name === 'webchat/ping') { + await context.sendActivity({ type: 'event', name: 'webchat/pong', value: context.activity.value }); + } + }); + this.onUnrecognizedActivityType(async (context: TurnContext) => { const { activity: { type }} = context; diff --git a/src/index.ts b/src/index.ts index c8e42e99..54b33077 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,3 +10,5 @@ window['MockBotAdapter'] = { WebChatAdapter, createDirectLine }; + +console.log(process.env.PUBLIC_URL) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 34e1d8c4..87aa69c9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,4 +10,4 @@ "include": [ "src" ] -} \ No newline at end of file +} diff --git a/webpack.config.js b/webpack.config.js index bc1b40b7..bd1d8054 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,11 @@ -const { join, resolve } = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const { DefinePlugin, HotModuleReplacementPlugin, NamedModulesPlugin } = require('webpack'); +const { join, resolve } = require('path'); const CopyWebpackPlugin = require('copy-webpack-plugin'); -const { HotModuleReplacementPlugin, NamedModulesPlugin } = require('webpack'); + +require('dotenv').config(); + +const PUBLIC_URL = process.env.PUBLIC_URL || '/'; module.exports = { entry: './src/index.ts', @@ -31,7 +35,10 @@ module.exports = { { from: resolve(__dirname, 'index.html'), to: '' }, { from: resolve(__dirname, 'src/assets'), to: 'assets' }, { from: resolve(__dirname, 'src/public'), to: 'public' } - ]) + ]), + new DefinePlugin({ + 'process.env.PUBLIC_URL': JSON.stringify(PUBLIC_URL) + }) ], resolve: { extensions: ['.css', '.js', '.ts']