R10 samples (#2706)
* CardAction image alt text and some cleanup (#2570) * Cards bot OAuthCard cleanup * dotnet: SuggestedActionsBot CardAction images and alt text * javascript: SuggestedActionsBot CardAction images and alt text * Add image_alt_text to python SuggestedActions CardActions (#2587) * Axsuarez/welcome with activity locale (#2593) * Updated welcomeBot to display the locale in the conversationupdate activity. * Update welcome_user_bot.py Touched file to trigger another build Co-authored-by: Gabo Gilabert <gabog@users.noreply.github.com> * Updated WelcomeBot projects with info on how to use the activity's locale (#2591) * dotnet updates: Updated WelcomeUser sample with information on how to get the locale for the incoming activity. Added some missing canellationTokens * JS update: Updated welcomeBot to display the locale in the conversationupdate activity. Applied consistent quotes to the messages being sent. * Added single quote to the method name. * Python: Merged dotnet readme changes (#2592) * JS: README parity (#2624) * Add dotnet immediate accept adapter sample to experimental (#2619) * Add ImmediateAcceptAdapter to experimental * readme update * Address feadback * Javascript: Add iFrame based Task Module sample (#2647) * Javascript: iFrame for 54.teams-task-module * Javascript: Suppressed method not allowed error due to for post to static page. * Update samples/javascript_nodejs/54.teams-task-module/models/taskmoduleuiconstants.js Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> * Update samples/javascript_nodejs/54.teams-task-module/models/taskmoduleresponsefactory.js Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> * Update samples/javascript_nodejs/54.teams-task-module/index.js Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> * Update samples/javascript_nodejs/54.teams-task-module/bots/teamsTaskModuleBot.js Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> * Update samples/javascript_nodejs/54.teams-task-module/bots/teamsTaskModuleBot.js Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> * TS teams messaging extensions search sample (#2629) * TS Teams conversation bot sample (#2627) * Zerryth/dotenv before bot (#2635) * 03.welcome-users - moved dotenv to top * 05.multi-turn-prompt - moved usage dotenv to top * 06.using-cards - moved usage dotenv to top * 07.using-adaptive-cards - moved usage dotenv to top * samples 11-21 - moved usage dotenv to top * samples 23-81, except 40 & 80 - moved usage dotenv to top * LG samples - moved usage dotenv to top * Python: Add iFrame based Task Module sample (#2670) * Python: 54.teams-task-module * Python: 54.teams-task-module, cleaned up code, added comments. * Python: Suppressed error from form post to static page. * Corrected manifest.json icon names * Python: Teams Task sample, manually serializing CardAction value. * TS Teams start new thread in channel sample (#2628) * TS Teams start new thread in channel sample * Updated .env file * added replace dependency in package.json * TS Teams messaging extensions action sample (#2630) * Update js version to 4.10.1 and fix eslint issues (#2705) * Update typescript samples to 4.10.1 * Update javascript to 4.10.1 and fix eslint issues * Update dotnet sample 3, 6, and 8 sdk vesrions (#2707) Co-authored-by: Axel Suárez <axsuarez@microsoft.com> Co-authored-by: Gabo Gilabert <gabog@users.noreply.github.com> Co-authored-by: tracyboehrer <tracyboehrer@users.noreply.github.com> Co-authored-by: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> Co-authored-by: Steven Kanberg <skanberg@kanbergs.com> Co-authored-by: Ashley Finafrock <35248895+Zerryth@users.noreply.github.com>
This commit is contained in:
Родитель
241834eb3e
Коммит
9c93ceb3cb
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using Microsoft.Bot.Schema;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton queue, used to transfer an ActivityWithClaims to the <see cref="HostedActivityService"/>.
|
||||
/// </summary>
|
||||
public class ActivityTaskQueue : IActivityTaskQueue
|
||||
{
|
||||
private SemaphoreSlim _signal = new SemaphoreSlim(0);
|
||||
private ConcurrentQueue<ActivityWithClaims> _activities = new ConcurrentQueue<ActivityWithClaims>();
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue an Activity, with Claims, to be processed on a background thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is assumed these claims have been authenticated via JwtTokenValidation.AuthenticateRequest
|
||||
/// before enqueueing.
|
||||
/// </remarks>
|
||||
/// <param name="claimsIdentity">Authenticated <see cref="ClaimsIdentity"/> used to process the
|
||||
/// activity.</param>
|
||||
/// <param name="activity"><see cref="Activity"/> to be processed.</param>
|
||||
public void QueueBackgroundActivity(ClaimsIdentity claimsIdentity, Activity activity)
|
||||
{
|
||||
if (claimsIdentity == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claimsIdentity));
|
||||
}
|
||||
|
||||
if (activity == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(activity));
|
||||
}
|
||||
|
||||
_activities.Enqueue(new ActivityWithClaims { ClaimsIdentity = claimsIdentity, Activity = activity});
|
||||
_signal.Release();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for a signal of an enqueued Activity with Claims to be processed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
|
||||
/// <returns>An ActivityWithClaims to be processed.
|
||||
/// </returns>
|
||||
/// <remarks>It is assumed these claims have already been authenticated via JwtTokenValidation.AuthenticateRequest.</remarks>
|
||||
public async Task<ActivityWithClaims> WaitForActivityAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _signal.WaitAsync(cancellationToken);
|
||||
|
||||
ActivityWithClaims dequeued;
|
||||
_activities.TryDequeue(out dequeued);
|
||||
|
||||
return dequeued;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using System.Security.Claims;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Activity with Claims which should already have been authenticated via JwtTokenValidation.AuthenticateRequest.
|
||||
/// </summary>
|
||||
public class ActivityWithClaims
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ClaimsIdentity"/> retrieved from a call to JwtTokenValidation.AuthenticateRequest.
|
||||
/// <seealso cref="ImmediateAcceptAdapter"/>
|
||||
/// </summary>
|
||||
public ClaimsIdentity ClaimsIdentity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Activity"/> which is to be processed.
|
||||
/// </summary>
|
||||
public Activity Activity { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="BackgroundService"/> implementation used to process activities with claims.
|
||||
/// <see href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice">More information.</see>
|
||||
/// </summary>
|
||||
public class HostedActivityService : BackgroundService
|
||||
{
|
||||
private readonly ILogger<HostedTaskService> _logger;
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
private readonly ConcurrentDictionary<ActivityWithClaims, Task> _activitiesProcessing = new ConcurrentDictionary<ActivityWithClaims, Task>();
|
||||
private IActivityTaskQueue _activityQueue;
|
||||
private readonly ImmediateAcceptAdapter _adapter;
|
||||
private readonly IBot _bot;
|
||||
private readonly int _shutdownTimeoutSeconds;
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="HostedActivityService"/> instance for processing Bot Framework Activities\
|
||||
/// on background threads.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is important to note that exceptions on the background thread are only logged in the <see cref="ILogger"/>.
|
||||
/// </remarks>
|
||||
/// <param name="config"><see cref="IConfiguration"/> used to retrieve ShutdownTimeoutSeconds from appsettings.</param>
|
||||
/// <param name="bot">IBot which will be used to process Activities.</param>
|
||||
/// <param name="adapter"><see cref="ImmediateAcceptAdapter"/> used to process Activities. </param>
|
||||
/// <param name="activityTaskQueue"><see cref="IActivityTaskQueue"/>Queue of activities to be processed. This class
|
||||
/// contains a semaphore which the BackgroundService waits on to be notified of activities to be processed.</param>
|
||||
/// <param name="logger">Logger to use for logging BackgroundService processing and exception information.</param>
|
||||
public HostedActivityService(IConfiguration config, IBot bot, ImmediateAcceptAdapter adapter, IActivityTaskQueue activityTaskQueue, ILogger<HostedTaskService> logger)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
if (adapter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(adapter));
|
||||
}
|
||||
|
||||
if (activityTaskQueue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(activityTaskQueue));
|
||||
}
|
||||
|
||||
_shutdownTimeoutSeconds = config.GetValue<int>("ShutdownTimeoutSeconds");
|
||||
_activityQueue = activityTaskQueue;
|
||||
_bot = bot;
|
||||
_adapter = adapter;
|
||||
_logger = logger ?? NullLogger<HostedTaskService>.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by BackgroundService when the hosting service is shutting down.
|
||||
/// </summary>
|
||||
/// <param name="stoppingToken"><see cref="CancellationToken"/> sent from BackgroundService for shutdown.</param>
|
||||
/// <returns>The Task to be executed asynchronously.</returns>
|
||||
public override async Task StopAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation("Queued Hosted Service is stopping.");
|
||||
|
||||
// Obtain a write lock and do not release it, preventing new tasks from starting
|
||||
if (_lock.TryEnterWriteLock(TimeSpan.FromSeconds(_shutdownTimeoutSeconds)))
|
||||
{
|
||||
// Wait for currently running tasks, but only n seconds.
|
||||
await Task.WhenAny(Task.WhenAll(_activitiesProcessing.Values), Task.Delay(TimeSpan.FromSeconds(_shutdownTimeoutSeconds)));
|
||||
}
|
||||
|
||||
await base.StopAsync(stoppingToken);
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation($"Queued Hosted Service is running.{Environment.NewLine}");
|
||||
|
||||
await BackgroundProcessing(stoppingToken);
|
||||
}
|
||||
|
||||
private async Task BackgroundProcessing(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
var activityWithClaims = await _activityQueue.WaitForActivityAsync(stoppingToken);
|
||||
if (activityWithClaims != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// The read lock will not be acquirable if the app is shutting down.
|
||||
// New tasks should not be starting during shutdown.
|
||||
if (_lock.TryEnterReadLock(500))
|
||||
{
|
||||
// Create the task which will execute the work item.
|
||||
var task = GetTaskFromWorkItem(activityWithClaims, stoppingToken)
|
||||
.ContinueWith(t =>
|
||||
{
|
||||
// After the work item completes, clear the running tasks of all completed tasks.
|
||||
foreach (var task in _activitiesProcessing.Where(tsk => tsk.Value.IsCompleted))
|
||||
{
|
||||
_activitiesProcessing.TryRemove(task.Key, out Task removed);
|
||||
}
|
||||
}, stoppingToken);
|
||||
|
||||
_activitiesProcessing.TryAdd(activityWithClaims, task);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Work item not processed. Server is shutting down.", nameof(BackgroundProcessing));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Task GetTaskFromWorkItem(ActivityWithClaims activityWithClaims, CancellationToken stoppingToken)
|
||||
{
|
||||
// Start the work item, and return the task
|
||||
return Task.Run(
|
||||
async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await _adapter.ProcessActivityAsync(activityWithClaims.ClaimsIdentity, activityWithClaims.Activity, _bot.OnTurnAsync, stoppingToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Bot Errors should be processed in the Adapter.OnTurnError.
|
||||
_logger.LogError(ex, "Error occurred executing WorkItem.", nameof(HostedActivityService));
|
||||
}
|
||||
}, stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using Microsoft.Bot.Schema;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a class used to transfer an ActivityWithClaims to the <see cref="HostedActivityService"/>.
|
||||
/// </summary>
|
||||
public interface IActivityTaskQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Enqueue an Activity, with Claims, to be processed on a background thread.
|
||||
/// before enqueueing.
|
||||
/// </summary>
|
||||
/// <remarks>It is assumed these claims have been authenticated via JwtTokenValidation.AuthenticateRequest.</remarks>
|
||||
/// <param name="claimsIdentity">Authenticated <see cref="ClaimsIdentity"/> used to process the
|
||||
/// activity.</param>
|
||||
/// <param name="activity"><see cref="Activity"/> to be processed.</param>
|
||||
void QueueBackgroundActivity(ClaimsIdentity claimsIdentity, Activity activity);
|
||||
|
||||
/// <summary>
|
||||
/// Wait for a signal of an enqueued Activity with Claims to be processed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
|
||||
/// <returns>An ActivityWithClaims to be processed.</returns>
|
||||
/// <remarks>It is assumed these claims have already been authenticated.</remarks>
|
||||
Task<ActivityWithClaims> WaitForActivityAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton queue, used to transfer a workitem to the <see cref="HostedTaskService"/>.
|
||||
/// </summary>
|
||||
public class BackgroundTaskQueue : IBackgroundTaskQueue
|
||||
{
|
||||
private ConcurrentQueue<Func<CancellationToken, Task>> _workItems = new ConcurrentQueue<Func<CancellationToken, Task>>();
|
||||
private SemaphoreSlim _signal = new SemaphoreSlim(0);
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue a work item to be processed on a background thread.
|
||||
/// </summary>
|
||||
/// <param name="workItem">The work item to be enqueued for execution, is defined as
|
||||
/// a function which takes a cancellation token.</param>
|
||||
public void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem)
|
||||
{
|
||||
if (workItem == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workItem));
|
||||
}
|
||||
|
||||
_workItems.Enqueue(workItem);
|
||||
_signal.Release();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for a signal of an enqueued work item to be processed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
|
||||
/// <returns>A function taking a cacnellation token, which needs to be processed.
|
||||
/// </returns>
|
||||
public async Task<Func<CancellationToken, Task>> DequeueAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _signal.WaitAsync(cancellationToken);
|
||||
|
||||
Func<CancellationToken, Task> dequeued;
|
||||
_workItems.TryDequeue(out dequeued);
|
||||
return dequeued;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="BackgroundService"/> implementation used to process work items on background threads.
|
||||
/// <see href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice">More information.</see>
|
||||
/// </summary>
|
||||
public class HostedTaskService : BackgroundService
|
||||
{
|
||||
private readonly ILogger<HostedTaskService> _logger;
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
private readonly ConcurrentDictionary<Func<CancellationToken,Task>, Task> _tasks = new ConcurrentDictionary<Func<CancellationToken, Task>, Task>();
|
||||
private readonly IBackgroundTaskQueue _taskQueue;
|
||||
private readonly int _shutdownTimeoutSeconds;
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="HostedTaskService"/> instance for processing work on a background thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is important to note that exceptions on the background thread are only logged in the <see cref="ILogger"/>.
|
||||
/// </remarks>
|
||||
/// <param name="config"><see cref="IConfiguration"/> used to retrieve ShutdownTimeoutSeconds from appsettings.</param>
|
||||
/// <param name="taskQueue"><see cref="IActivityTaskQueue"/> implementation where tasks are queued to be processed.</param>
|
||||
/// <param name="logger"><see cref="ILogger"/> iplementation, for logging includig background thread exception information.</param>
|
||||
public HostedTaskService(IConfiguration config, IBackgroundTaskQueue taskQueue, ILogger<HostedTaskService> logger)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
if (taskQueue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(taskQueue));
|
||||
}
|
||||
|
||||
_shutdownTimeoutSeconds = config.GetValue<int>("ShutdownTimeoutSeconds");
|
||||
_taskQueue = taskQueue;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by BackgroundService when the hosting service is shutting down.
|
||||
/// </summary>
|
||||
/// <param name="stoppingToken"><see cref="CancellationToken"/> sent from BackgroundService for shutdown.</param>
|
||||
/// <returns>The Task to be executed asynchronously.</returns>
|
||||
public override async Task StopAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation("Queued Hosted Service is stopping.");
|
||||
|
||||
// Obtain a write lock and do not release it, preventing new tasks from starting
|
||||
if (_lock.TryEnterWriteLock(TimeSpan.FromSeconds(_shutdownTimeoutSeconds)))
|
||||
{
|
||||
// Wait for currently running tasks, but only n seconds.
|
||||
await Task.WhenAny(Task.WhenAll(_tasks.Values), Task.Delay(TimeSpan.FromSeconds(_shutdownTimeoutSeconds)));
|
||||
}
|
||||
|
||||
await base.StopAsync(stoppingToken);
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation($"Queued Hosted Service is running.{Environment.NewLine}");
|
||||
|
||||
await BackgroundProcessing(stoppingToken);
|
||||
}
|
||||
|
||||
private async Task BackgroundProcessing(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
var workItem = await _taskQueue.DequeueAsync(stoppingToken);
|
||||
if (workItem != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// The read lock will not be acquirable if the app is shutting down.
|
||||
// New tasks should not be starting during shutdown.
|
||||
if (_lock.TryEnterReadLock(500))
|
||||
{
|
||||
var task = GetTaskFromWorkItem(workItem, stoppingToken)
|
||||
.ContinueWith(t =>
|
||||
{
|
||||
// After the work item completes, clear the running tasks of all completed tasks.
|
||||
foreach (var task in _tasks.Where(tsk => tsk.Value.IsCompleted))
|
||||
{
|
||||
_tasks.TryRemove(task.Key, out Task removed);
|
||||
}
|
||||
}, stoppingToken);
|
||||
|
||||
_tasks.TryAdd(workItem, task);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Work item not processed. Server is shutting down.", nameof(BackgroundProcessing));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Task GetTaskFromWorkItem(Func<CancellationToken, Task> workItem, CancellationToken stoppingToken)
|
||||
{
|
||||
// Start the work item, and return the task
|
||||
return Task.Run(
|
||||
async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await workItem(stoppingToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Bot Errors should be processed in the Adapter.OnTurnError.
|
||||
_logger.LogError(ex, "Error occurred executing WorkItem.", nameof(HostedTaskService));
|
||||
}
|
||||
}, stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ImmediateAcceptBot.BackgroundQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a class used to transfer a workitem to the <see cref="HostedTaskService"/>.
|
||||
/// </summary>
|
||||
public interface IBackgroundTaskQueue
|
||||
{
|
||||
/// <summary>
|
||||
/// Enqueue a work item to be processed on a background thread.
|
||||
/// </summary>
|
||||
/// <param name="workItem">The work item to be enqueued for execution, is defined as
|
||||
/// a function which takes a cancellation token.</param>
|
||||
void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);
|
||||
|
||||
/// <summary>
|
||||
/// Wait for a signal of an enqueued work item to be processed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
|
||||
/// <returns>A function taking a cacnellation token, which needs to be processed.
|
||||
/// </returns>
|
||||
Task<Func<CancellationToken, Task>> DequeueAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.9.2
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ImmediateAcceptBot.BackgroundQueue;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace ImmediateAcceptBot.Bots
|
||||
{
|
||||
public class EchoBot : ActivityHandler
|
||||
{
|
||||
private readonly IBackgroundTaskQueue _taskQueue;
|
||||
private readonly string _botId;
|
||||
private readonly int _shutdownTimeoutSeconds;
|
||||
|
||||
public EchoBot(IConfiguration config, IBackgroundTaskQueue taskQueue)
|
||||
{
|
||||
if (taskQueue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(taskQueue));
|
||||
}
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
_shutdownTimeoutSeconds = config.GetValue<int>("ShutdownTimeoutSeconds");
|
||||
_botId = config.GetValue<string>("MicrosoftAppId");
|
||||
_botId = string.IsNullOrEmpty(_botId) ? Guid.NewGuid().ToString() : _botId;
|
||||
_taskQueue = taskQueue;
|
||||
}
|
||||
|
||||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var text = turnContext.Activity.Text.ToLower().Trim();
|
||||
var hasText = !string.IsNullOrEmpty(text);
|
||||
bool pause = hasText && text.Contains("pause");
|
||||
bool background = hasText && text.Contains("background");
|
||||
|
||||
if(background && pause)
|
||||
{
|
||||
await turnContext.SendActivityAsync($"I cannot do a 'pause' and 'background' both. These are exclusive commands.", cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
await SendHelp(turnContext, cancellationToken);
|
||||
}
|
||||
else if (pause || background)
|
||||
{
|
||||
await HandlePauseOrBackground(turnContext, text, cancellationToken);
|
||||
}
|
||||
else if (!hasText || text.Contains("help"))
|
||||
{
|
||||
await SendHelp(turnContext, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var replyText = $"Echo: {text} (send 'help' if you are not sure what to do)";
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandlePauseOrBackground(ITurnContext turnContext, string text, CancellationToken cancellationToken)
|
||||
{
|
||||
var splitText = text.Split(" ");
|
||||
int seconds = splitText.Select((s, i) => int.TryParse(s, out i) ? i : 0).FirstOrDefault(i => i > 0);
|
||||
|
||||
// validate seconds were received in the text
|
||||
if (seconds < 1 || seconds > _shutdownTimeoutSeconds)
|
||||
{
|
||||
await turnContext.SendActivityAsync($"Please enter seconds < {_shutdownTimeoutSeconds} > 0, and processing type. Example: 4 seconds or 4 background", cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the user sent a message with, send it back to them after the pause/background timeout
|
||||
string message = splitText.Length > 2 ? splitText.Where(word =>
|
||||
!new[]
|
||||
{
|
||||
"seconds",
|
||||
"second",
|
||||
"pause",
|
||||
"background",
|
||||
seconds.ToString()
|
||||
}
|
||||
.Contains(word.ToLower()))
|
||||
.Aggregate(string.Empty, (current, next) => current + " " + next) : string.Empty;
|
||||
if (text.Contains("pause"))
|
||||
{
|
||||
await turnContext.SendActivityAsync($"okay, pausing {seconds} seconds", cancellationToken: cancellationToken);
|
||||
Thread.Sleep(TimeSpan.FromSeconds(seconds));
|
||||
await turnContext.SendActivityAsync($"finished pausing {seconds} seconds {message}", cancellationToken: cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
await turnContext.SendActivityAsync($"okay, I will background message you after: {seconds} seconds", cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
_taskQueue.QueueBackgroundWorkItem(async cancelToken => await ProactiveMessageCallbackAsync(turnContext.Adapter, turnContext.Activity.GetConversationReference(), message, seconds, cancelToken).ConfigureAwait(false));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProactiveMessageCallbackAsync(BotAdapter adapter, ConversationReference conversationReference, string message, int seconds, CancellationToken cancellationToken)
|
||||
{
|
||||
// Pause on the background thread for the number of seconds specified, then load the conversation and message the user.
|
||||
// This simulates a long running process.
|
||||
Thread.Sleep(TimeSpan.FromSeconds(seconds));
|
||||
|
||||
await adapter.ContinueConversationAsync(_botId, conversationReference, async (innerContext, innerCancellationToken) =>
|
||||
{
|
||||
await innerContext.SendActivityAsync(string.IsNullOrWhiteSpace(message) ? $"background notice after {seconds} seconds" : $"background msg {seconds} {message}");
|
||||
// Could load a dialog stack here, and resume
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SendHelp(ITurnContext turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text("send: 4 seconds ... and i will pause for 4 seconds while processing your message."), cancellationToken);
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text("send: 4 background ... and i will push your message to an additional background thread to process for 4 seconds."), cancellationToken);
|
||||
}
|
||||
|
||||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var member in membersAdded)
|
||||
{
|
||||
if (member.Id != turnContext.Activity.Recipient.Id)
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text("Hi! I'm a background processing bot. All incoming messages are processed on a background thread."), cancellationToken);
|
||||
await SendHelp(turnContext, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.9.2
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace ImmediateAcceptBot.Controllers
|
||||
{
|
||||
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot
|
||||
// implementation at runtime. Multiple different IBot implementations running at different endpoints can be
|
||||
// achieved by specifying a more specific type for the bot constructor argument.
|
||||
[Route("api/messages")]
|
||||
[ApiController]
|
||||
public class BotController : ControllerBase
|
||||
{
|
||||
private readonly IBotFrameworkHttpAdapter _adapter;
|
||||
private readonly IBot _bot;
|
||||
|
||||
public BotController(ImmediateAcceptAdapter adapter, IBot bot)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_bot = bot;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[HttpGet]
|
||||
public async Task PostAsync()
|
||||
{
|
||||
// Delegate the processing of the HTTP POST to the adapter.
|
||||
await _adapter.ProcessAsync(Request, Response, _bot);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"groupLocation": {
|
||||
"value": ""
|
||||
},
|
||||
"groupName": {
|
||||
"value": ""
|
||||
},
|
||||
"appId": {
|
||||
"value": ""
|
||||
},
|
||||
"appSecret": {
|
||||
"value": ""
|
||||
},
|
||||
"botId": {
|
||||
"value": ""
|
||||
},
|
||||
"botSku": {
|
||||
"value": ""
|
||||
},
|
||||
"newAppServicePlanName": {
|
||||
"value": ""
|
||||
},
|
||||
"newAppServicePlanSku": {
|
||||
"value": {
|
||||
"name": "S1",
|
||||
"tier": "Standard",
|
||||
"size": "S1",
|
||||
"family": "S",
|
||||
"capacity": 1
|
||||
}
|
||||
},
|
||||
"newAppServicePlanLocation": {
|
||||
"value": ""
|
||||
},
|
||||
"newWebAppName": {
|
||||
"value": ""
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"appId": {
|
||||
"value": ""
|
||||
},
|
||||
"appSecret": {
|
||||
"value": ""
|
||||
},
|
||||
"botId": {
|
||||
"value": ""
|
||||
},
|
||||
"botSku": {
|
||||
"value": ""
|
||||
},
|
||||
"newAppServicePlanName": {
|
||||
"value": ""
|
||||
},
|
||||
"newAppServicePlanSku": {
|
||||
"value": {
|
||||
"name": "S1",
|
||||
"tier": "Standard",
|
||||
"size": "S1",
|
||||
"family": "S",
|
||||
"capacity": 1
|
||||
}
|
||||
},
|
||||
"appServicePlanLocation": {
|
||||
"value": ""
|
||||
},
|
||||
"existingAppServicePlan": {
|
||||
"value": ""
|
||||
},
|
||||
"newWebAppName": {
|
||||
"value": ""
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"groupLocation": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Specifies the location of the Resource Group."
|
||||
}
|
||||
},
|
||||
"groupName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Specifies the name of the Resource Group."
|
||||
}
|
||||
},
|
||||
"appId": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
|
||||
}
|
||||
},
|
||||
"appSecret": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings."
|
||||
}
|
||||
},
|
||||
"botId": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
|
||||
}
|
||||
},
|
||||
"botSku": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
|
||||
}
|
||||
},
|
||||
"newAppServicePlanName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the App Service Plan."
|
||||
}
|
||||
},
|
||||
"newAppServicePlanSku": {
|
||||
"type": "object",
|
||||
"defaultValue": {
|
||||
"name": "S1",
|
||||
"tier": "Standard",
|
||||
"size": "S1",
|
||||
"family": "S",
|
||||
"capacity": 1
|
||||
},
|
||||
"metadata": {
|
||||
"description": "The SKU of the App Service Plan. Defaults to Standard values."
|
||||
}
|
||||
},
|
||||
"newAppServicePlanLocation": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The location of the App Service Plan. Defaults to \"westus\"."
|
||||
}
|
||||
},
|
||||
"newWebAppName": {
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"metadata": {
|
||||
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"appServicePlanName": "[parameters('newAppServicePlanName')]",
|
||||
"resourcesLocation": "[parameters('newAppServicePlanLocation')]",
|
||||
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
|
||||
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
|
||||
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"name": "[parameters('groupName')]",
|
||||
"type": "Microsoft.Resources/resourceGroups",
|
||||
"apiVersion": "2018-05-01",
|
||||
"location": "[parameters('groupLocation')]",
|
||||
"properties": {
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Resources/deployments",
|
||||
"apiVersion": "2018-05-01",
|
||||
"name": "storageDeployment",
|
||||
"resourceGroup": "[parameters('groupName')]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"mode": "Incremental",
|
||||
"template": {
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {},
|
||||
"variables": {},
|
||||
"resources": [
|
||||
{
|
||||
"comments": "Create a new App Service Plan",
|
||||
"type": "Microsoft.Web/serverfarms",
|
||||
"name": "[variables('appServicePlanName')]",
|
||||
"apiVersion": "2018-02-01",
|
||||
"location": "[variables('resourcesLocation')]",
|
||||
"sku": "[parameters('newAppServicePlanSku')]",
|
||||
"properties": {
|
||||
"name": "[variables('appServicePlanName')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"comments": "Create a Web App using the new App Service Plan",
|
||||
"type": "Microsoft.Web/sites",
|
||||
"apiVersion": "2015-08-01",
|
||||
"location": "[variables('resourcesLocation')]",
|
||||
"kind": "app",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/serverfarms/', variables('appServicePlanName'))]"
|
||||
],
|
||||
"name": "[variables('webAppName')]",
|
||||
"properties": {
|
||||
"name": "[variables('webAppName')]",
|
||||
"serverFarmId": "[variables('appServicePlanName')]",
|
||||
"siteConfig": {
|
||||
"appSettings": [
|
||||
{
|
||||
"name": "WEBSITE_NODE_DEFAULT_VERSION",
|
||||
"value": "10.14.1"
|
||||
},
|
||||
{
|
||||
"name": "MicrosoftAppId",
|
||||
"value": "[parameters('appId')]"
|
||||
},
|
||||
{
|
||||
"name": "MicrosoftAppPassword",
|
||||
"value": "[parameters('appSecret')]"
|
||||
}
|
||||
],
|
||||
"cors": {
|
||||
"allowedOrigins": [
|
||||
"https://botservice.hosting.portal.azure.net",
|
||||
"https://hosting.onecloud.azure-test.net/"
|
||||
]
|
||||
},
|
||||
"webSocketsEnabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-12-01",
|
||||
"type": "Microsoft.BotService/botServices",
|
||||
"name": "[parameters('botId')]",
|
||||
"location": "global",
|
||||
"kind": "bot",
|
||||
"sku": {
|
||||
"name": "[parameters('botSku')]"
|
||||
},
|
||||
"properties": {
|
||||
"name": "[parameters('botId')]",
|
||||
"displayName": "[parameters('botId')]",
|
||||
"endpoint": "[variables('botEndpoint')]",
|
||||
"msaAppId": "[parameters('appId')]",
|
||||
"developerAppInsightsApplicationId": null,
|
||||
"developerAppInsightKey": null,
|
||||
"publishingCredentials": null,
|
||||
"storageResourceId": null
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"appId": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings."
|
||||
}
|
||||
},
|
||||
"appSecret": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"."
|
||||
}
|
||||
},
|
||||
"botId": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable."
|
||||
}
|
||||
},
|
||||
"botSku": {
|
||||
"defaultValue": "F0",
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1."
|
||||
}
|
||||
},
|
||||
"newAppServicePlanName": {
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"metadata": {
|
||||
"description": "The name of the new App Service Plan."
|
||||
}
|
||||
},
|
||||
"newAppServicePlanSku": {
|
||||
"type": "object",
|
||||
"defaultValue": {
|
||||
"name": "S1",
|
||||
"tier": "Standard",
|
||||
"size": "S1",
|
||||
"family": "S",
|
||||
"capacity": 1
|
||||
},
|
||||
"metadata": {
|
||||
"description": "The SKU of the App Service Plan. Defaults to Standard values."
|
||||
}
|
||||
},
|
||||
"appServicePlanLocation": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The location of the App Service Plan."
|
||||
}
|
||||
},
|
||||
"existingAppServicePlan": {
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"metadata": {
|
||||
"description": "Name of the existing App Service Plan used to create the Web App for the bot."
|
||||
}
|
||||
},
|
||||
"newWebAppName": {
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"metadata": {
|
||||
"description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]",
|
||||
"useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]",
|
||||
"servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]",
|
||||
"resourcesLocation": "[parameters('appServicePlanLocation')]",
|
||||
"webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]",
|
||||
"siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]",
|
||||
"botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.",
|
||||
"type": "Microsoft.Web/serverfarms",
|
||||
"condition": "[not(variables('useExistingAppServicePlan'))]",
|
||||
"name": "[variables('servicePlanName')]",
|
||||
"apiVersion": "2018-02-01",
|
||||
"location": "[variables('resourcesLocation')]",
|
||||
"sku": "[parameters('newAppServicePlanSku')]",
|
||||
"properties": {
|
||||
"name": "[variables('servicePlanName')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"comments": "Create a Web App using an App Service Plan",
|
||||
"type": "Microsoft.Web/sites",
|
||||
"apiVersion": "2015-08-01",
|
||||
"location": "[variables('resourcesLocation')]",
|
||||
"kind": "app",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/serverfarms/', variables('servicePlanName'))]"
|
||||
],
|
||||
"name": "[variables('webAppName')]",
|
||||
"properties": {
|
||||
"name": "[variables('webAppName')]",
|
||||
"serverFarmId": "[variables('servicePlanName')]",
|
||||
"siteConfig": {
|
||||
"appSettings": [
|
||||
{
|
||||
"name": "WEBSITE_NODE_DEFAULT_VERSION",
|
||||
"value": "10.14.1"
|
||||
},
|
||||
{
|
||||
"name": "MicrosoftAppId",
|
||||
"value": "[parameters('appId')]"
|
||||
},
|
||||
{
|
||||
"name": "MicrosoftAppPassword",
|
||||
"value": "[parameters('appSecret')]"
|
||||
}
|
||||
],
|
||||
"cors": {
|
||||
"allowedOrigins": [
|
||||
"https://botservice.hosting.portal.azure.net",
|
||||
"https://hosting.onecloud.azure-test.net/"
|
||||
]
|
||||
},
|
||||
"webSocketsEnabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2017-12-01",
|
||||
"type": "Microsoft.BotService/botServices",
|
||||
"name": "[parameters('botId')]",
|
||||
"location": "global",
|
||||
"kind": "bot",
|
||||
"sku": {
|
||||
"name": "[parameters('botSku')]"
|
||||
},
|
||||
"properties": {
|
||||
"name": "[parameters('botId')]",
|
||||
"displayName": "[parameters('botId')]",
|
||||
"endpoint": "[variables('botEndpoint')]",
|
||||
"msaAppId": "[parameters('appId')]",
|
||||
"developerAppInsightsApplicationId": null,
|
||||
"developerAppInsightKey": null,
|
||||
"publishingCredentials": null,
|
||||
"storageResourceId": null
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/sites/', variables('webAppName'))]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// Generated with Bot Builder V4 SDK Template for Visual Studio CoreBot v4.9.2
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ImmediateAcceptBot.BackgroundQueue;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Builder.TraceExtensions;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ImmediateAcceptBot
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ImmediateAcceptAdapter"/>will authenticate the incoming request, and queue to be
|
||||
/// processed by the configured background service if possible.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the activity is Not an Invoke, and DeliveryMode is Not ExpectReplies, and this
|
||||
/// is NOT a Get request to upgrade to WebSockets, then the activity will be enqueuedto be processed
|
||||
/// on a background thread.
|
||||
/// </remarks>
|
||||
public class ImmediateAcceptAdapter : BotFrameworkHttpAdapter, IBotFrameworkHttpAdapter
|
||||
{
|
||||
private readonly IActivityTaskQueue _activityTaskQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of <see cref="ImmediateAcceptAdapter"/>.
|
||||
/// </summary>
|
||||
/// <param name="configuration"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="activityTaskQueue"></param>
|
||||
public ImmediateAcceptAdapter(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger, IActivityTaskQueue activityTaskQueue)
|
||||
: base(configuration, logger)
|
||||
{
|
||||
_activityTaskQueue = activityTaskQueue;
|
||||
|
||||
OnTurnError = async (turnContext, exception) =>
|
||||
{
|
||||
// Log any leaked exception from the application.
|
||||
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
|
||||
|
||||
// Send a message to the user
|
||||
await turnContext.SendActivityAsync("The bot encountered an error or bug.");
|
||||
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
|
||||
|
||||
// Send a trace activity, which will be displayed in the Bot Framework Emulator
|
||||
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can be called from inside a POST method on any Controller implementation. If the activity is Not an Invoke, and
|
||||
/// DeliveryMode is Not ExpectReplies, and this is NOT a Get request to upgrade to WebSockets, then the activity will be enqueued
|
||||
/// to be processed on a background thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note, this is an ImmediateAccept and BackgroundProcessing override of:
|
||||
/// Task IBotFrameworkHttpAdapter.ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default);
|
||||
/// </remarks>
|
||||
/// <param name="httpRequest">The HTTP request object, typically in a POST handler by a Controller.</param>
|
||||
/// <param name="httpResponse">The HTTP response object.</param>
|
||||
/// <param name="bot">The bot implementation.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive
|
||||
/// notice of cancellation.</param>
|
||||
/// <returns>A task that represents the work queued to execute.</returns>
|
||||
async Task IBotFrameworkHttpAdapter.ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (httpRequest == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpRequest));
|
||||
}
|
||||
|
||||
if (httpResponse == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpResponse));
|
||||
}
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
// Get is a socket exchange request, so should be processed by base BotFrameworkHttpAdapter
|
||||
if (httpRequest.Method == HttpMethods.Get)
|
||||
{
|
||||
await base.ProcessAsync(httpRequest, httpResponse, bot, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deserialize the incoming Activity
|
||||
var activity = await HttpHelper.ReadRequestAsync<Activity>(httpRequest).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(activity?.Type))
|
||||
{
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||
}
|
||||
else if (activity.Type == ActivityTypes.Invoke || activity.DeliveryMode == DeliveryModes.ExpectReplies)
|
||||
{
|
||||
// NOTE: Invoke and ExpectReplies cannot be performed async, the response must be written before the calling thread is released.
|
||||
await base.ProcessAsync(httpRequest, httpResponse, bot, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the auth header from the inbound http request
|
||||
var authHeader = httpRequest.Headers["Authorization"];
|
||||
|
||||
try
|
||||
{
|
||||
// If authentication passes, queue a work item to process the inbound activity with the bot
|
||||
var claimsIdentity = await JwtTokenValidation.AuthenticateRequest(activity, authHeader, CredentialProvider, ChannelProvider, HttpClient).ConfigureAwait(false);
|
||||
|
||||
// Queue the activity to be processed by the ActivityBackgroundService
|
||||
_activityTaskQueue.QueueBackgroundActivity(claimsIdentity, activity);
|
||||
|
||||
// Activity has been queued to process, so return Ok immediately
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.OK;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
// handle unauthorized here as this layer creates the http response
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.10.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.9.2
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace ImmediateAcceptBot
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:3978",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"EchoBot": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:3979;http://localhost:3978",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
# Immediate Accept Bot
|
||||
|
||||
Built starting from Bot Framework v4 echo bot sample.
|
||||
|
||||
This example demonstrates how to create a simple bot that accepts input from the user and echoes it back. All incoming activities are processed on a background thread, alleviating 15 second timeout concerns.
|
||||
|
||||
ImmediateAcceptAdapter verifies the authorization header, adds the message to a Microsoft.Extensions.Hosting.BackgroundService (HostedActivityService) for processing, and writes HttpStatusCode.OK to HttpResponse. This causes all messages sent by the bot to effectively be proactive.
|
||||
|
||||
Note: This bot demonstrates how to extend in process execution of incoming messages, passed the 15 second timeout. In general, long running processes should be executed by a Web Job or Azure Function and not a web application hosting server.
|
||||
|
||||
## ImmediateAcceptAdapter.cs
|
||||
|
||||
New method in BotFrameworkHttpAdapter implementation:
|
||||
|
||||
```cs
|
||||
/// <summary>
|
||||
/// This method can be called from inside a POST method on any Controller implementation. If the activity is Not an Invoke, and
|
||||
/// DeliveryMode is Not ExpectReplies, and this is NOT a Get request to upgrade to WebSockets, then the activity will be enqueued
|
||||
/// to be processed on a background thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note, this is an ImmediateAccept and BackgroundProcessing override of:
|
||||
/// Task IBotFrameworkHttpAdapter.ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default);
|
||||
/// </remarks>
|
||||
/// <param name="httpRequest">The HTTP request object, typically in a POST handler by a Controller.</param>
|
||||
/// <param name="httpResponse">The HTTP response object.</param>
|
||||
/// <param name="bot">The bot implementation.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive
|
||||
/// notice of cancellation.</param>
|
||||
/// <returns>A task that represents the work queued to execute.</returns>
|
||||
async Task IBotFrameworkHttpAdapter.ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (httpRequest == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpRequest));
|
||||
}
|
||||
|
||||
if (httpResponse == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpResponse));
|
||||
}
|
||||
|
||||
if (bot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
// Get is a socket exchange request, so should be processed by base BotFrameworkHttpAdapter
|
||||
if (httpRequest.Method == HttpMethods.Get)
|
||||
{
|
||||
await base.ProcessAsync(httpRequest, httpResponse, bot, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deserialize the incoming Activity
|
||||
var activity = await HttpHelper.ReadRequestAsync<Activity>(httpRequest).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(activity?.Type))
|
||||
{
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||
}
|
||||
else if (activity.Type == ActivityTypes.Invoke || activity.DeliveryMode == DeliveryModes.ExpectReplies)
|
||||
{
|
||||
// NOTE: Invoke and ExpectReplies cannot be performed async, the response must be written before the calling thread is released.
|
||||
await base.ProcessAsync(httpRequest, httpResponse, bot, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the auth header from the inbound http request
|
||||
var authHeader = httpRequest.Headers["Authorization"];
|
||||
|
||||
try
|
||||
{
|
||||
// If authentication passes, queue a work item to process the inbound activity with the bot
|
||||
var claimsIdentity = await JwtTokenValidation.AuthenticateRequest(activity, authHeader, CredentialProvider, ChannelProvider, HttpClient).ConfigureAwait(false);
|
||||
|
||||
// Queue the activity to be processed by the ActivityBackgroundService
|
||||
_activityTaskQueue.QueueBackgroundActivity(claimsIdentity, activity);
|
||||
|
||||
// Activity has been queued to process, so return Ok immediately
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.OK;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
// handle unauthorized here as this layer creates the http response
|
||||
httpResponse.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Startup.cs
|
||||
|
||||
Register BackgroundServices and classes:
|
||||
|
||||
```cs
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllers().AddNewtonsoftJson();
|
||||
|
||||
// Activity specific BackgroundService for processing athenticated activities.
|
||||
services.AddHostedService<HostedActivityService>();
|
||||
// Generic BackgroundService for processing tasks.
|
||||
services.AddHostedService<HostedTaskService>();
|
||||
|
||||
// BackgroundTaskQueue and ActivityTaskQueue are the entry points for
|
||||
// the enqueueing activities or tasks to be processed by the BackgroundService.
|
||||
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
|
||||
services.AddSingleton<IActivityTaskQueue, ActivityTaskQueue>();
|
||||
|
||||
// Configure the ShutdownTimeout based on appsettings.
|
||||
services.Configure<HostOptions>(opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(Configuration.GetValue<int>("ShutdownTimeoutSeconds")));
|
||||
|
||||
// Create the Bot Framework Adapter with error handling enabled.
|
||||
services.AddSingleton<ImmediateAcceptAdapter>();
|
||||
|
||||
// Create the bot. In this case the ASP Controller and ImmediateAcceptAdapter is expecting an IBot.
|
||||
services.AddSingleton<IBot, EchoBot>();
|
||||
}
|
||||
```
|
||||
|
||||
## Interacting with the Bot
|
||||
|
||||
send: 4 seconds ... and the bot will pause for 4 seconds while processing your message.
|
||||
send: 4 background ... and the bot will push your message to an additional background thread to process for 4 seconds.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
QueuedHostedService is from https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/host/hosted-services/samples/3.x/BackgroundTasksSample
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// Generated with Bot Builder V4 SDK Template for Visual Studio EchoBot v4.9.2
|
||||
|
||||
using System;
|
||||
using ImmediateAcceptBot.BackgroundQueue;
|
||||
using ImmediateAcceptBot.Bots;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace ImmediateAcceptBot
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllers().AddNewtonsoftJson();
|
||||
|
||||
// Activity specific BackgroundService for processing athenticated activities.
|
||||
services.AddHostedService<HostedActivityService>();
|
||||
// Generic BackgroundService for processing tasks.
|
||||
services.AddHostedService<HostedTaskService>();
|
||||
|
||||
// BackgroundTaskQueue and ActivityTaskQueue are the entry points for
|
||||
// the enqueueing activities or tasks to be processed by the BackgroundService.
|
||||
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
|
||||
services.AddSingleton<IActivityTaskQueue, ActivityTaskQueue>();
|
||||
|
||||
// Configure the ShutdownTimeout based on appsettings.
|
||||
services.Configure<HostOptions>(opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(Configuration.GetValue<int>("ShutdownTimeoutSeconds")));
|
||||
|
||||
// Create the Bot Framework Adapter with error handling enabled.
|
||||
services.AddSingleton<ImmediateAcceptAdapter>();
|
||||
|
||||
// Create the bot. In this case the ASP Controller and ImmediateAcceptAdapter is expecting an IBot.
|
||||
services.AddSingleton<IBot, EchoBot>();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseDefaultFiles()
|
||||
.UseStaticFiles()
|
||||
.UseWebSockets()
|
||||
.UseRouting()
|
||||
.UseAuthorization()
|
||||
.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
// app.UseHttpsRedirection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"MicrosoftAppId": "",
|
||||
"MicrosoftAppPassword": "",
|
||||
"ShutdownTimeoutSeconds": "60"
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>ImmediateAcceptBot</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: Segoe UI;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
background-image: url("data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 4638.9 651.6' style='enable-background:new 0 0 4638.9 651.6;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%2355A0E0;%7D .st1%7Bfill:none;%7D .st2%7Bfill:%230058A8;%7D .st3%7Bfill:%23328BD8;%7D .st4%7Bfill:%23B6DCF1;%7D .st5%7Bopacity:0.2;fill:url(%23SVGID_1_);enable-background:new ;%7D%0A%3C/style%3E%3Crect y='1.1' class='st0' width='4640' height='646.3'/%3E%3Cpath class='st1' d='M3987.8,323.6L4310.3,1.1h-65.6l-460.1,460.1c-17.5,17.5-46.1,17.5-63.6,0L3260.9,1.1H0v646.3h3660.3 L3889,418.7c17.5-17.5,46.1-17.5,63.6,0l228.7,228.7h66.6l-260.2-260.2C3970.3,369.8,3970.3,341.1,3987.8,323.6z'/%3E%3Cpath class='st2' d='M3784.6,461.2L4244.7,1.1h-983.9l460.1,460.1C3738.4,478.7,3767.1,478.7,3784.6,461.2z'/%3E%3Cpath class='st3' d='M4640,1.1h-329.8l-322.5,322.5c-17.5,17.5-17.5,46.1,0,63.6l260.2,260.2H4640L4640,1.1L4640,1.1z'/%3E%3Cpath class='st4' d='M3889,418.8l-228.7,228.7h521.1l-228.7-228.7C3935.2,401.3,3906.5,401.3,3889,418.8z'/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='3713.7576' y1='438.1175' x2='3911.4084' y2='14.2535' gradientTransform='matrix(1 0 0 -1 0 641.3969)'%3E%3Cstop offset='0' style='stop-color:%23FFFFFF;stop-opacity:0.5'/%3E%3Cstop offset='1' style='stop-color:%23FFFFFF'/%3E%3C/linearGradient%3E%3Cpath class='st5' d='M3952.7,124.5c-17.5-17.5-46.1-17.5-63.6,0l-523,523h1109.6L3952.7,124.5z'/%3E%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
background-position: right;
|
||||
background-color: #55A0E0;
|
||||
width: 100%;
|
||||
font-size: 44px;
|
||||
height: 120px;
|
||||
color: white;
|
||||
padding: 30px 0 40px 0px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
background-image: url("data:image/svg+xml;utf8,%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20150.2%20125%22%20style%3D%22enable-background%3Anew%200%200%20150.2%20125%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23FFFFFF%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.5%22%20class%3D%22st0%22%20width%3D%22149.7%22%20height%3D%22125%22/%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M59%2C102.9L21.8%2C66c-3.5-3.5-3.5-9.1%2C0-12.5l37-36.5l2.9%2C3l-37%2C36.4c-1.8%2C1.8-1.8%2C4.7%2C0%2C6.6l37.2%2C37L59%2C102.9z%22%0A%09%09/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M92.5%2C102.9l-3-3l37.2-37c0.9-0.9%2C1.4-2%2C1.4-3.3c0-1.2-0.5-2.4-1.4-3.3L89.5%2C20l2.9-3l37.2%2C36.4%0A%09%09c1.7%2C1.7%2C2.6%2C3.9%2C2.6%2C6.3s-0.9%2C4.6-2.6%2C6.3L92.5%2C102.9z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M90.1%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C98.1%2C64.7%2C94.4%2C68.4%2C90.1%2C68.4z%0A%09%09%20M90.1%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S91.9%2C56.5%2C90.1%2C56.5z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M61.4%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C69.5%2C64.7%2C65.8%2C68.4%2C61.4%2C68.4z%0A%09%09%20M61.4%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S63.3%2C56.5%2C61.4%2C56.5z%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
float: left;
|
||||
height: 140px;
|
||||
width: 140px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
padding-left: 1%;
|
||||
color: #FFFFFF;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 72px;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.35px;
|
||||
line-height: 96px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-inner-container {
|
||||
min-width: 480px;
|
||||
max-width: 1366px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-inner-container::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.main-content-area {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
color: #000000;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 46px;
|
||||
font-weight: 300;
|
||||
line-height: 62px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
color: #808080;
|
||||
font-size: 24px;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.main-text-p1 {
|
||||
padding-top: 48px;
|
||||
padding-bottom: 28px;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
height: 32px;
|
||||
width: 571px;
|
||||
color: #808080;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 32px;
|
||||
padding-top: 28px;
|
||||
}
|
||||
|
||||
.how-to-build-section {
|
||||
padding-top: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.how-to-build-section>h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.35px;
|
||||
line-height: 22px;
|
||||
margin: 0 0 24px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.step-container {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-container dl {
|
||||
border-left: 1px solid #A0A0A0;
|
||||
display: block;
|
||||
padding: 0 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.step-container dl>dt::before {
|
||||
background-color: white;
|
||||
border: 1px solid #A0A0A0;
|
||||
border-radius: 100%;
|
||||
content: '';
|
||||
left: 47px;
|
||||
height: 11px;
|
||||
position: absolute;
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
.step-container dl>.test-bullet::before {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
.step-container dl>dt {
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.step-container dl>dd {
|
||||
font-size: inherit;
|
||||
line-height: 20px;
|
||||
margin-left: 0;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.step-container:last-child dl {
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ctaLink {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: #006AB1;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
padding: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.ctaLink:focus {
|
||||
outline: 1px solid #00bcf2;
|
||||
}
|
||||
|
||||
.ctaLink:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
display: flex;
|
||||
height: 38px;
|
||||
margin-right: 15px;
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
.step-icon>div {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ms-logo-container {
|
||||
min-width: 580px;
|
||||
max-width: 980px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transition: bottom 400ms;
|
||||
}
|
||||
|
||||
.ms-logo {
|
||||
float: right;
|
||||
background-image: url("data:image/svg+xml;utf8,%0A%3Csvg%20version%3D%221.1%22%20id%3D%22MS-symbol%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20400%20120%22%20style%3D%22enable-background%3Anew%200%200%20400%20120%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23737474%3B%7D%0A%09.st2%7Bfill%3A%23D63F26%3B%7D%0A%09.st3%7Bfill%3A%23167D3E%3B%7D%0A%09.st4%7Bfill%3A%232E76BC%3B%7D%0A%09.st5%7Bfill%3A%23FDB813%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.6%22%20class%3D%22st0%22%20width%3D%22398.7%22%20height%3D%22119%22/%3E%0A%3Cpath%20class%3D%22st1%22%20d%3D%22M171.3%2C38.4v43.2h-7.5V47.7h-0.1l-13.4%2C33.9h-5l-13.7-33.9h-0.1v33.9h-6.9V38.4h10.8l12.4%2C32h0.2l13.1-32H171.3%0A%09z%20M177.6%2C41.7c0-1.2%2C0.4-2.2%2C1.3-3c0.9-0.8%2C1.9-1.2%2C3.1-1.2c1.3%2C0%2C2.4%2C0.4%2C3.2%2C1.3c0.8%2C0.8%2C1.3%2C1.8%2C1.3%2C3c0%2C1.2-0.4%2C2.2-1.3%2C3%0A%09c-0.9%2C0.8-1.9%2C1.2-3.2%2C1.2s-2.3-0.4-3.1-1.2C178%2C43.8%2C177.6%2C42.8%2C177.6%2C41.7z%20M185.7%2C50.6v31h-7.3v-31H185.7z%20M207.8%2C76.3%0A%09c1.1%2C0%2C2.3-0.3%2C3.6-0.8c1.3-0.5%2C2.5-1.2%2C3.6-2v6.8c-1.2%2C0.7-2.5%2C1.2-4%2C1.5c-1.5%2C0.3-3.1%2C0.5-4.9%2C0.5c-4.6%2C0-8.3-1.4-11.1-4.3%0A%09c-2.9-2.9-4.3-6.6-4.3-11c0-5%2C1.5-9.1%2C4.4-12.3c2.9-3.2%2C7-4.8%2C12.4-4.8c1.4%2C0%2C2.7%2C0.2%2C4.1%2C0.5c1.4%2C0.4%2C2.5%2C0.8%2C3.3%2C1.2v7%0A%09c-1.1-0.8-2.3-1.5-3.4-1.9c-1.2-0.5-2.4-0.7-3.6-0.7c-2.9%2C0-5.2%2C0.9-7%2C2.8c-1.8%2C1.9-2.7%2C4.4-2.7%2C7.6c0%2C3.1%2C0.8%2C5.6%2C2.5%2C7.3%0A%09C202.6%2C75.4%2C204.9%2C76.3%2C207.8%2C76.3z%20M235.7%2C50.1c0.6%2C0%2C1.1%2C0%2C1.6%2C0.1s0.9%2C0.2%2C1.2%2C0.3v7.4c-0.4-0.3-0.9-0.5-1.7-0.8%0A%09c-0.7-0.3-1.6-0.4-2.7-0.4c-1.8%2C0-3.3%2C0.8-4.5%2C2.3c-1.2%2C1.5-1.9%2C3.8-1.9%2C7v15.6h-7.3v-31h7.3v4.9h0.1c0.7-1.7%2C1.7-3%2C3-4%0A%09C232.2%2C50.6%2C233.8%2C50.1%2C235.7%2C50.1z%20M238.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3%0A%09c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5c-4.8%2C0-8.6-1.4-11.4-4.2C240.3%2C75.3%2C238.9%2C71.4%2C238.9%2C66.6z%0A%09%20M246.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5%0A%09c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7C247.2%2C60.5%2C246.5%2C63%2C246.5%2C66.3z%20M281.5%2C58.8c0%2C1%2C0.3%2C1.9%2C1%2C2.5%0A%09c0.7%2C0.6%2C2.1%2C1.3%2C4.4%2C2.2c2.9%2C1.2%2C5%2C2.5%2C6.1%2C3.9c1.2%2C1.5%2C1.8%2C3.2%2C1.8%2C5.3c0%2C2.9-1.1%2C5.3-3.4%2C7c-2.2%2C1.8-5.3%2C2.7-9.1%2C2.7%0A%09c-1.3%2C0-2.7-0.2-4.3-0.5c-1.6-0.3-2.9-0.7-4-1.2v-7.2c1.3%2C0.9%2C2.8%2C1.7%2C4.3%2C2.2c1.5%2C0.5%2C2.9%2C0.8%2C4.2%2C0.8c1.6%2C0%2C2.9-0.2%2C3.6-0.7%0A%09c0.8-0.5%2C1.2-1.2%2C1.2-2.3c0-1-0.4-1.9-1.2-2.5c-0.8-0.7-2.4-1.5-4.6-2.4c-2.7-1.1-4.6-2.4-5.7-3.8c-1.1-1.4-1.7-3.2-1.7-5.4%0A%09c0-2.8%2C1.1-5.1%2C3.3-6.9c2.2-1.8%2C5.1-2.7%2C8.6-2.7c1.1%2C0%2C2.3%2C0.1%2C3.6%2C0.4c1.3%2C0.2%2C2.5%2C0.6%2C3.4%2C0.9v6.9c-1-0.6-2.1-1.2-3.4-1.7%0A%09c-1.3-0.5-2.6-0.7-3.8-0.7c-1.4%2C0-2.5%2C0.3-3.2%2C0.8C281.9%2C57.1%2C281.5%2C57.8%2C281.5%2C58.8z%20M297.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2%0A%09c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5%0A%09c-4.8%2C0-8.6-1.4-11.4-4.2C299.4%2C75.3%2C297.9%2C71.4%2C297.9%2C66.6z%20M305.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6%0A%09c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7%0A%09C306.3%2C60.5%2C305.5%2C63%2C305.5%2C66.3z%20M353.9%2C56.6h-10.9v25h-7.4v-25h-5.2v-6h5.2v-4.3c0-3.3%2C1.1-5.9%2C3.2-8c2.1-2.1%2C4.8-3.1%2C8.1-3.1%0A%09c0.9%2C0%2C1.7%2C0%2C2.4%2C0.1c0.7%2C0.1%2C1.3%2C0.2%2C1.8%2C0.4V42c-0.2-0.1-0.7-0.3-1.3-0.5c-0.6-0.2-1.3-0.3-2.1-0.3c-1.5%2C0-2.7%2C0.5-3.5%2C1.4%0A%09s-1.2%2C2.4-1.2%2C4.2v3.7h10.9v-7l7.3-2.2v9.2h7.4v6h-7.4v14.5c0%2C1.9%2C0.3%2C3.3%2C1%2C4c0.7%2C0.8%2C1.8%2C1.2%2C3.3%2C1.2c0.4%2C0%2C0.9-0.1%2C1.5-0.3%0A%09c0.6-0.2%2C1.1-0.4%2C1.6-0.7v6c-0.5%2C0.3-1.2%2C0.5-2.3%2C0.7c-1.1%2C0.2-2.1%2C0.3-3.2%2C0.3c-3.1%2C0-5.4-0.8-6.9-2.5c-1.5-1.6-2.3-4.1-2.3-7.4%0A%09V56.6z%22/%3E%0A%3Cg%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2224%22%20class%3D%22st2%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2224%22%20class%3D%22st3%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2261.8%22%20class%3D%22st4%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2261.8%22%20class%3D%22st5%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
|
||||
}
|
||||
|
||||
.ms-logo-container>div {
|
||||
min-height: 60px;
|
||||
width: 150px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 90px 0px 0 20px;
|
||||
min-width: 480px;
|
||||
max-width: 1366px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.column {
|
||||
float: left;
|
||||
width: 45%;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.download-the-emulator {
|
||||
height: 20px;
|
||||
color: #0063B1;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
|
||||
.how-to-iframe {
|
||||
max-width: 700px !important;
|
||||
min-width: 650px !important;
|
||||
height: 700px !important;
|
||||
}
|
||||
|
||||
.remove-frame-height {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1300px) {
|
||||
.ms-logo {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 40x;
|
||||
}
|
||||
|
||||
.column {
|
||||
float: none;
|
||||
padding-top: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ms-logo-container {
|
||||
padding-top: 30px;
|
||||
min-width: 480px;
|
||||
max-width: 650px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 20px 0px 0 20px;
|
||||
min-width: 480px;
|
||||
max-width: 650px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1370px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-size: auto 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1230px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-size: auto 200px;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 44px;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 632px) {
|
||||
.header-text {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 10px 0px 0 10px;
|
||||
max-width: 490px !important;
|
||||
min-width: 410px !important;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.step-container dl>dd {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.column {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
height: 110px;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.how-to-iframe {
|
||||
max-width: 480px !important;
|
||||
min-width: 400px !important;
|
||||
height: 650px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.remove-frame-height {
|
||||
max-height: 10px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
loadFrame();
|
||||
});
|
||||
var loadFrame = function () {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute("id", "iframe");
|
||||
var offLineHTMLContent = "";
|
||||
var frameElement = document.getElementById("how-to-iframe");
|
||||
if (window.navigator.onLine) {
|
||||
iframe.src = 'https://docs.botframework.com/static/abs/pages/f5.htm';
|
||||
iframe.setAttribute("scrolling", "no");
|
||||
iframe.setAttribute("frameborder", "0");
|
||||
iframe.setAttribute("width", "100%");
|
||||
iframe.setAttribute("height", "100%");
|
||||
var frameDiv = document.getElementById("how-to-iframe");
|
||||
frameDiv.appendChild(iframe);
|
||||
} else {
|
||||
frameElement.classList.add("remove-frame-height");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="header">
|
||||
<div class="header-inner-container">
|
||||
<div class="header-icon" style="display: inline-block"></div>
|
||||
<div class="header-text" style="display: inline-block">ImmediateAcceptBot Bot</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="row">
|
||||
<div class="column" class="main-content-area">
|
||||
<div class="content-title">Your bot is ready!</div>
|
||||
<div class="main-text main-text-p1">You can test your bot in the Bot Framework Emulator<br />
|
||||
by connecting to http://localhost:3978/api/messages.</div>
|
||||
<div class="main-text download-the-emulator"><a class="ctaLink"
|
||||
href="https://aka.ms/bot-framework-F5-download-emulator" target="_blank">Download the Emulator</a>
|
||||
</div>
|
||||
<div class="main-text">Visit <a class="ctaLink" href="https://aka.ms/bot-framework-F5-abs-home"
|
||||
target="_blank">Azure
|
||||
Bot Service</a> to register your bot and add it to<br />
|
||||
various channels. The bot's endpoint URL typically looks
|
||||
like this:</div>
|
||||
<div class="endpoint">https://<i>your_bots_hostname</i>/api/messages</div>
|
||||
</div>
|
||||
<div class="column how-to-iframe" id="how-to-iframe"></div>
|
||||
</div>
|
||||
<div class="ms-logo-container">
|
||||
<div class="ms-logo"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -34,11 +34,16 @@ namespace Microsoft.BotBuilderSamples
|
|||
"read more information at: " +
|
||||
"https://aka.ms/about-botframework-welcome-user";
|
||||
|
||||
private const string LocaleMessage = "You can use the activity's 'GetLocale()' method to welcome the user " +
|
||||
"using the locale received from the channel. " +
|
||||
"If you are using the Emulator, you can set this value in Settings.";
|
||||
|
||||
|
||||
private const string PatternMessage = "It is a good pattern to use this event to send general greeting" +
|
||||
"to user, explaining what your bot can do. In this example, the bot " +
|
||||
"handles 'hello', 'hi', 'help' and 'intro'. Try it now, type 'hi'";
|
||||
|
||||
private BotState _userState;
|
||||
private readonly BotState _userState;
|
||||
|
||||
// Initializes a new instance of the "WelcomeUserBot" class.
|
||||
public WelcomeUserBot(UserState userState)
|
||||
|
@ -46,12 +51,11 @@ namespace Microsoft.BotBuilderSamples
|
|||
_userState = userState;
|
||||
}
|
||||
|
||||
|
||||
// Greet when users are added to the conversation.
|
||||
// Note that all channels do not send the conversation update activity.
|
||||
// If you find that this bot works in the emulator, but does not in
|
||||
// another channel the reason is most likely that the channel does not
|
||||
// send this activity.
|
||||
// Greet when users are added to the conversation.
|
||||
// Note that all channels do not send the conversation update activity.
|
||||
// If you find that this bot works in the emulator, but does not in
|
||||
// another channel the reason is most likely that the channel does not
|
||||
// send this activity.
|
||||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var member in membersAdded)
|
||||
|
@ -60,6 +64,7 @@ namespace Microsoft.BotBuilderSamples
|
|||
{
|
||||
await turnContext.SendActivityAsync($"Hi there - {member.Name}. {WelcomeMessage}", cancellationToken: cancellationToken);
|
||||
await turnContext.SendActivityAsync(InfoMessage, cancellationToken: cancellationToken);
|
||||
await turnContext.SendActivityAsync($"{LocaleMessage} Current locale is '{turnContext.Activity.GetLocale()}'.", cancellationToken: cancellationToken);
|
||||
await turnContext.SendActivityAsync(PatternMessage, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +73,7 @@ namespace Microsoft.BotBuilderSamples
|
|||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var welcomeUserStateAccessor = _userState.CreateProperty<WelcomeUserState>(nameof(WelcomeUserState));
|
||||
var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState());
|
||||
var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState(), cancellationToken);
|
||||
|
||||
if (didBotWelcomeUser.DidBotWelcomeUser == false)
|
||||
{
|
||||
|
@ -77,7 +82,7 @@ namespace Microsoft.BotBuilderSamples
|
|||
// the channel should sends the user name in the 'From' object
|
||||
var userName = turnContext.Activity.From.Name;
|
||||
|
||||
await turnContext.SendActivityAsync($"You are seeing this message because this was your first message ever to this bot.", cancellationToken: cancellationToken);
|
||||
await turnContext.SendActivityAsync("You are seeing this message because this was your first message ever to this bot.", cancellationToken: cancellationToken);
|
||||
await turnContext.SendActivityAsync($"It is a good practice to welcome the user and provide personal greeting. For example, welcome {userName}.", cancellationToken: cancellationToken);
|
||||
}
|
||||
else
|
||||
|
@ -101,25 +106,27 @@ namespace Microsoft.BotBuilderSamples
|
|||
}
|
||||
|
||||
// Save any state changes.
|
||||
await _userState.SaveChangesAsync(turnContext);
|
||||
await _userState.SaveChangesAsync(turnContext, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
private static async Task SendIntroCardAsync(ITurnContext turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var card = new HeroCard();
|
||||
card.Title = "Welcome to Bot Framework!";
|
||||
card.Text = @"Welcome to Welcome Users bot sample! This Introduction card
|
||||
var card = new HeroCard
|
||||
{
|
||||
Title = "Welcome to Bot Framework!",
|
||||
Text = @"Welcome to Welcome Users bot sample! This Introduction card
|
||||
is a great way to introduce your Bot to the user and suggest
|
||||
some things to get them started. We use this opportunity to
|
||||
recommend a few next steps for learning more creating and deploying bots.";
|
||||
card.Images = new List<CardImage>() { new CardImage("https://aka.ms/bf-welcome-card-image") };
|
||||
card.Buttons = new List<CardAction>()
|
||||
{
|
||||
new CardAction(ActionTypes.OpenUrl, "Get an overview", null, "Get an overview", "Get an overview", "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"),
|
||||
new CardAction(ActionTypes.OpenUrl, "Ask a question", null, "Ask a question", "Ask a question", "https://stackoverflow.com/questions/tagged/botframework"),
|
||||
new CardAction(ActionTypes.OpenUrl, "Learn how to deploy", null, "Learn how to deploy", "Learn how to deploy", "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"),
|
||||
recommend a few next steps for learning more creating and deploying bots.",
|
||||
Images = new List<CardImage>() { new CardImage("https://aka.ms/bf-welcome-card-image") },
|
||||
Buttons = new List<CardAction>()
|
||||
{
|
||||
new CardAction(ActionTypes.OpenUrl, "Get an overview", null, "Get an overview", "Get an overview", "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"),
|
||||
new CardAction(ActionTypes.OpenUrl, "Ask a question", null, "Ask a question", "Ask a question", "https://stackoverflow.com/questions/tagged/botframework"),
|
||||
new CardAction(ActionTypes.OpenUrl, "Learn how to deploy", null, "Learn how to deploy", "Learn how to deploy", "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var response = MessageFactory.Attachment(card.ToAttachment());
|
||||
await turnContext.SendActivityAsync(response, cancellationToken);
|
||||
}
|
||||
|
|
|
@ -147,25 +147,4 @@ namespace Microsoft.BotBuilderSamples
|
|||
return cardOptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// NOTE: This is a temporary class to support ToAttachment for OAuthCards, until the next sdk released.
|
||||
/// </summary>
|
||||
static class OauthCardExtension
|
||||
{
|
||||
public static Attachment ToAttachment(this OAuthCard card)
|
||||
{
|
||||
return CreateAttachment(card, OAuthCard.ContentType);
|
||||
}
|
||||
|
||||
private static Attachment CreateAttachment<T>(T card, string contentType)
|
||||
{
|
||||
return new Attachment
|
||||
{
|
||||
Content = card,
|
||||
ContentType = contentType,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,39 +4,16 @@ Bot Framework v4 using cards bot sample
|
|||
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a bot that uses rich cards to enhance your bot design.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [.NET Core SDK](https://dotnet.microsoft.com/download) version 3.1
|
||||
|
||||
```bash
|
||||
# determine dotnet version
|
||||
dotnet --version
|
||||
```
|
||||
|
||||
## To try this sample
|
||||
|
||||
- Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Microsoft/botbuilder-samples.git
|
||||
```
|
||||
|
||||
- Run the bot from a terminal or from Visual Studio:
|
||||
|
||||
A) From a terminal, navigate to `samples/csharp_dotnetcore/06.using-cards`
|
||||
|
||||
```bash
|
||||
# run the bot
|
||||
dotnet run
|
||||
```
|
||||
|
||||
B) Or from Visual Studio
|
||||
|
||||
- Launch Visual Studio
|
||||
- File -> Open -> Project/Solution
|
||||
- Navigate to `samples/csharp_dotnetcore/06.using-cards` folder
|
||||
- Select `CardBot.csproj` file
|
||||
- Press `F5` to run the project
|
||||
```bash
|
||||
git clone https://github.com/Microsoft/botbuilder-samples.git
|
||||
```
|
||||
- In a terminal, navigate to `botbuilder-samples\samples\python\02.echo-bot` folder
|
||||
- Activate your desired virtual environment
|
||||
- In the terminal, type `pip install -r requirements.txt`
|
||||
- Run your bot with `python app.py`
|
||||
|
||||
## Testing the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -76,7 +53,6 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt
|
|||
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
|
||||
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
|
||||
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
|
||||
- [.NET Core CLI tools](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x)
|
||||
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
|
||||
- [Azure Portal](https://portal.azure.com)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
|
|
|
@ -14,8 +14,7 @@ namespace Microsoft.BotBuilderSamples
|
|||
// can tap to provide input.
|
||||
public class SuggestedActionsBot : ActivityHandler
|
||||
{
|
||||
public const string WelcomeText = @"This bot will introduce you to suggestedActions.
|
||||
Please answer the question:";
|
||||
public const string WelcomeText = "This bot will introduce you to suggestedActions. Please answer the question:";
|
||||
|
||||
|
||||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
|
||||
|
@ -90,9 +89,9 @@ namespace Microsoft.BotBuilderSamples
|
|||
{
|
||||
Actions = new List<CardAction>()
|
||||
{
|
||||
new CardAction() { Title = "Red", Type = ActionTypes.ImBack, Value = "Red" },
|
||||
new CardAction() { Title = "Yellow", Type = ActionTypes.ImBack, Value = "Yellow" },
|
||||
new CardAction() { Title = "Blue", Type = ActionTypes.ImBack, Value = "Blue" },
|
||||
new CardAction() { Title = "Red", Type = ActionTypes.ImBack, Value = "Red", Image = "https://via.placeholder.com/20/FF0000?text=R", ImageAltText = "R" },
|
||||
new CardAction() { Title = "Yellow", Type = ActionTypes.ImBack, Value = "Yellow", Image = "https://via.placeholder.com/20/FFFF00?text=Y", ImageAltText = "Y" },
|
||||
new CardAction() { Title = "Blue", Type = ActionTypes.ImBack, Value = "Blue", Image = "https://via.placeholder.com/20/0000FF?text=B", ImageAltText = "B" },
|
||||
},
|
||||
};
|
||||
await turnContext.SendActivityAsync(reply, cancellationToken);
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
{
|
||||
"MicrosoftAppId": "",
|
||||
"MicrosoftAppPassword": "",
|
||||
"QnA-sample-qna-kbId": "",
|
||||
"QnA-sample-qna-endpointKey": "",
|
||||
"QnA-sample-qna-hostname": ""
|
||||
"MicrosoftAppPassword": ""
|
||||
}
|
||||
|
|
|
@ -50,9 +50,17 @@ The bot maintains user state to track the user's answers.
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Deploy the bot to Azure
|
||||
## Interacting with the bot
|
||||
|
||||
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions.
|
||||
A bot is inherently stateless. Once your bot is deployed, it may not run in the same process or on the same machine from one turn to the next.
|
||||
However, your bot may need to track the context of a conversation, so that it can manage its behavior and remember answers to previous questions.
|
||||
|
||||
In this example, the bot's state is used to a track number of messages.
|
||||
|
||||
- We use the bot's turn handler and user and conversation state properties to manage the flow of the conversation and the collection of input.
|
||||
- We ask the user a series of questions; parse, validate, and normalize their answers; and then save their input.
|
||||
|
||||
This sample is intended to be run and tested locally and is not designed to be deployed to Azure.
|
||||
|
||||
## Further reading
|
||||
|
||||
|
@ -62,7 +70,5 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt
|
|||
- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
|
||||
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
|
||||
- [.NET Core CLI tools](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x)
|
||||
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
|
||||
- [Azure Portal](https://portal.azure.com)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
- [Bot Storage](https://docs.microsoft.com/azure/bot-service/dotnet/bot-builder-dotnet-state?view=azure-bot-service-3.0&viewFallbackFrom=azure-bot-service-4.0)
|
|
@ -16,7 +16,7 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder-core": "~4.9.1",
|
||||
"botbuilder-core": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"path": "^0.12.7",
|
||||
"readline": "^1.3.0"
|
||||
|
|
|
@ -43,7 +43,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -51,6 +51,10 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Interacting with the bot
|
||||
|
||||
Enter text in the emulator. The text will be echoed back by the bot.
|
||||
|
||||
## Deploy the bot to Azure
|
||||
|
||||
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions.
|
||||
|
@ -64,7 +68,6 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt
|
|||
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
|
||||
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
|
||||
- [Azure Portal](https://portal.azure.com)
|
||||
- [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
- [Restify](https://www.npmjs.com/package/restify)
|
||||
- [dotenv](https://www.npmjs.com/package/dotenv)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"url": "https://github.com"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
module.exports = {
|
||||
"extends": "standard",
|
||||
"rules": {
|
||||
"quotes": ["error", "single", {
|
||||
"avoidEscape": true,
|
||||
"allowTemplateLiterals": true
|
||||
}],
|
||||
"semi": [2, "always"],
|
||||
"indent": [2, 4],
|
||||
"no-return-await": 0,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# welcome-users
|
||||
# Welcome Users
|
||||
|
||||
Bot Framework v4 welcome users bot sample
|
||||
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), is shows how to welcome a user when join the conversation.
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), is shows how to welcome users when they join the conversation.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -43,7 +43,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -51,9 +51,9 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Welcoming Users
|
||||
## Interacting with the bot
|
||||
|
||||
The primary goal when creating any bot is to engage your user in a meaningful conversation. One of the best ways to achieve this goal is to ensure that from the moment a user first connects, they understand your bot’s main purpose and capabilities, the reason your bot was created. See [Send welcome message to users](https://aka.ms/botframework-welcome-instructions) for additional information on how a bot can welcome uers to a conversation.
|
||||
The primary goal when creating any bot is to engage your user in a meaningful conversation. One of the best ways to achieve this goal is to ensure that from the moment a user first connects, they understand your bot’s main purpose and capabilities, the reason your bot was created. See [Send welcome message to users](https://aka.ms/botframework-welcome-instructions) for additional information on how a bot can welcome users to a conversation.
|
||||
|
||||
## Deploy the bot to Azure
|
||||
|
||||
|
@ -68,7 +68,6 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt
|
|||
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
|
||||
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
|
||||
- [Azure Portal](https://portal.azure.com)
|
||||
- [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
- [Restify](https://www.npmjs.com/package/restify)
|
||||
- [dotenv](https://www.npmjs.com/package/dotenv)
|
||||
|
|
|
@ -70,14 +70,18 @@ class WelcomeBot extends ActivityHandler {
|
|||
// context.activity.membersAdded === context.activity.recipient.Id indicates the
|
||||
// bot was added to the conversation, and the opposite indicates this is a user.
|
||||
if (context.activity.membersAdded[idx].id !== context.activity.recipient.id) {
|
||||
await context.sendActivity('Welcome to the \'Welcome User\' Bot. This bot will introduce you to welcoming and greeting users.');
|
||||
await context.sendActivity("You are seeing this message because the bot received at least one 'ConversationUpdate' " +
|
||||
'event, indicating you (and possibly others) joined the conversation. If you are using the emulator, ' +
|
||||
'pressing the \'Start Over\' button to trigger this event again. The specifics of the \'ConversationUpdate\' ' +
|
||||
'event depends on the channel. You can read more information at https://aka.ms/about-botframework-welcome-user');
|
||||
await context.sendActivity('It is a good pattern to use this event to send general greeting to user, explaining what your bot can do. ' +
|
||||
'In this example, the bot handles \'hello\', \'hi\', \'help\' and \'intro\'. ' +
|
||||
'Try it now, type \'hi\'');
|
||||
await context.sendActivity(`Welcome to the 'Welcome User' Bot. This bot will introduce you to welcoming and greeting users.`);
|
||||
await context.sendActivity(`You are seeing this message because the bot received at least one 'ConversationUpdate' ` +
|
||||
`event, indicating you (and possibly others) joined the conversation. If you are using the emulator, ` +
|
||||
`pressing the 'Start Over' button to trigger this event again. The specifics of the 'ConversationUpdate' ` +
|
||||
`event depends on the channel. You can read more information at https://aka.ms/about-botframework-welcome-user`);
|
||||
await context.sendActivity(`You can use the activity's 'locale' property to welcome the user ` +
|
||||
`using the locale received from the channel. ` +
|
||||
`If you are using the Emulator, you can set this value in Settings. ` +
|
||||
`Current locale is '${ context.activity.locale }'`);
|
||||
await context.sendActivity(`It is a good pattern to use this event to send general greeting to user, explaining what your bot can do. ` +
|
||||
`In this example, the bot handles 'hello', 'hi', 'help' and 'intro'. ` +
|
||||
`Try it now, type 'hi'`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -11,10 +16,6 @@ const { BotFrameworkAdapter, UserState, MemoryStorage } = require('botbuilder');
|
|||
|
||||
const { WelcomeBot } = require('./bots/welcomeBot');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create bot adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about bot adapter.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# multi turn prompt sample
|
||||
# Multi-turn prompt
|
||||
|
||||
Bot Framework v4 multi-turn prompt bot sample
|
||||
|
||||
|
@ -43,7 +43,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -51,7 +51,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Prompts
|
||||
## Interacting with the bot
|
||||
|
||||
A conversation between a bot and a user often involves asking (prompting) the user for information, parsing the user's response,
|
||||
and then acting on that information. This sample demonstrates how to prompt users for information using the different prompt types
|
||||
|
@ -76,7 +76,6 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt
|
|||
- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0)
|
||||
- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest)
|
||||
- [Azure Portal](https://portal.azure.com)
|
||||
- [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
- [Restify](https://www.npmjs.com/package/restify)
|
||||
- [dotenv](https://www.npmjs.com/package/dotenv)
|
||||
|
|
|
@ -186,8 +186,7 @@ class UserProfileDialog extends ComponentDialog {
|
|||
|
||||
// If none of the attachments are valid images, the retry prompt should be sent.
|
||||
return !!validImages.length;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await promptContext.context.sendActivity('No attachments received. Proceeding without a profile picture...');
|
||||
|
||||
// We can return true from a validator function even if Recognized.Succeeded is false.
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
const restify = require('restify');
|
||||
const path = require('path');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Import required bot services.
|
||||
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
|
||||
const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = require('botbuilder');
|
||||
|
@ -12,10 +16,6 @@ const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = req
|
|||
const { DialogBot } = require('./bots/dialogBot');
|
||||
const { UserProfileDialog } = require('./dialogs/userProfileDialog');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create the adapter. See https://aka.ms/about-bot-adapter to learn more about using information from
|
||||
// the .bot file when configuring your adapter.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"path": "^0.12.7",
|
||||
"restify": "~8.5.1"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Using-Cards
|
||||
# Using Cards
|
||||
|
||||
Bot Framework v4 using cards bot sample
|
||||
|
||||
This bot has been created using [Microsoft Bot Framework][1], it shows how to create a bot that uses rich cards to enhance your bot design.
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a bot that uses rich cards to enhance your bot design.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -43,7 +43,7 @@ This bot has been created using [Microsoft Bot Framework][1], it shows how to cr
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -51,7 +51,7 @@ This bot has been created using [Microsoft Bot Framework][1], it shows how to cr
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Rich Cards
|
||||
## Interacting with the bot
|
||||
|
||||
Most channels support rich content. In this sample we explore the different types of rich cards your bot may use. A key to good bot design is to send interactive media, such as Rich Cards. There are several different types of Rich Cards, which are as follows:
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -15,9 +18,6 @@ const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = req
|
|||
const { RichCardsBot } = require('./bots/richCardsBot');
|
||||
const { MainDialog } = require('./dialogs/mainDialog');
|
||||
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter. See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: process.env.MicrosoftAppId,
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# using adaptive cards sample
|
||||
# Using Adaptive Cards
|
||||
|
||||
Bot Framework v4 using adaptive cards bot sample
|
||||
|
||||
|
@ -43,7 +43,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -51,7 +51,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Adaptive Cards
|
||||
## Interacting with the bot
|
||||
|
||||
Card authors describe their content as a simple JSON object. That content can then be rendered natively inside a host application, automatically adapting to the look and feel of the host. For example, Contoso Bot can author an Adaptive Card through the Bot Framework, and when delivered to Cortana, it will look and feel like a Cortana card. When that same payload is sent to Microsoft Teams, it will look and feel like Microsoft Teams. As more host apps start to support Adaptive Cards, that same payload will automatically light up inside these applications, yet still feel entirely native to the app. Users win because everything feels familiar. Host apps win because they control the user experience. Card authors win because their content gets broader reach without any additional work.
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -10,10 +15,6 @@ const { BotFrameworkAdapter } = require('botbuilder');
|
|||
|
||||
const { AdaptiveCardsBot } = require('./bots/adaptiveCardsBot');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter. See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: process.env.MicrosoftAppID,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# suggested actions
|
||||
# Suggested Actions
|
||||
|
||||
Bot Framework v4 suggested actions bot sample
|
||||
Bot Framework v4 using adaptive cards bot sample
|
||||
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to use suggested actions. Suggested actions enable your bot to present buttons that the user can tap to provide input.
|
||||
|
||||
|
@ -43,7 +43,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -51,7 +51,7 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Suggested Actions
|
||||
## Interacting with the bot
|
||||
|
||||
Suggested actions enable your bot to present buttons that the user can tap to provide input. Suggested actions appear close to the composer and enhance user experience.
|
||||
They enable the user to answer a question or make a selection with a simple tap of a button, rather than having to type a response with a keyboard.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const { ActivityHandler, MessageFactory } = require('botbuilder');
|
||||
const { ActionTypes } = require('botframework-schema');
|
||||
|
||||
class SuggestedActionsBot extends ActivityHandler {
|
||||
constructor() {
|
||||
|
@ -59,7 +60,31 @@ class SuggestedActionsBot extends ActivityHandler {
|
|||
* @param {TurnContext} turnContext A TurnContext instance containing all the data needed for processing this conversation turn.
|
||||
*/
|
||||
async sendSuggestedActions(turnContext) {
|
||||
var reply = MessageFactory.suggestedActions(['Red', 'Yellow', 'Blue'], 'What is the best color?');
|
||||
const cardActions = [
|
||||
{
|
||||
type: ActionTypes.PostBack,
|
||||
title: 'Red',
|
||||
value: 'Red',
|
||||
image: 'https://via.placeholder.com/20/FF0000?text=R',
|
||||
imageAltText: 'R'
|
||||
},
|
||||
{
|
||||
type: ActionTypes.PostBack,
|
||||
title: 'Yellow',
|
||||
value: 'Yellow',
|
||||
image: 'https://via.placeholder.com/20/FFFF00?text=Y',
|
||||
imageAltText: 'Y'
|
||||
},
|
||||
{
|
||||
type: ActionTypes.PostBack,
|
||||
title: 'Blue',
|
||||
value: 'Blue',
|
||||
image: 'https://via.placeholder.com/20/0000FF?text=B',
|
||||
imageAltText: 'B'
|
||||
}
|
||||
];
|
||||
|
||||
var reply = MessageFactory.suggestedActions(cardActions, 'What is the best color?');
|
||||
await turnContext.sendActivity(reply);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -10,10 +15,6 @@ const { BotFrameworkAdapter } = require('botbuilder');
|
|||
|
||||
const { SuggestedActionsBot } = require('./bots/suggestedActionsBot');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter. See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: process.env.MicrosoftAppId,
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "^4.10.1",
|
||||
"botframework-schema": "^4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
|
||||
// Note: Ensure you have a .env file and include QnAMakerKnowledgeBaseId, QnAMakerEndpointKey and QnAMakerHost.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -15,10 +20,6 @@ const { ActivityTypes } = require('botbuilder-core');
|
|||
// The bot.
|
||||
const { QnABot } = require('./bots/QnABot');
|
||||
|
||||
// Note: Ensure you have a .env file and include QnAMakerKnowledgeBaseId, QnAMakerEndpointKey and QnAMakerHost.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-ai": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-ai": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
# Setting up LUIS via CLI:
|
||||
|
||||
This README contains information on how to create and deploy a LUIS application. When the bot is ready to be deployed to production, we recommend creating a LUIS Endpoint Resource for usage with your LUIS App.
|
||||
|
||||
> _For instructions on how to create a LUIS Application via the LUIS portal, see these Quickstart steps:_
|
||||
> 1. _[Quickstart: Create a new app in the LUIS portal][Quickstart-create]_
|
||||
> 2. _[Quickstart: Deploy an app in the LUIS portal][Quickstart-deploy]_
|
||||
|
||||
[Quickstart-create]: https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-build-app
|
||||
[Quickstart-deploy]:https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-deploy-app
|
||||
|
||||
## Table of Contents:
|
||||
|
||||
- [Prerequisites](#Prerequisites)
|
||||
- [Import a new LUIS Application using a local LUIS application](#Import-a-new-LUIS-Application-using-a-local-LUIS-application)
|
||||
- [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#How-to-create-a-LUIS-Endpoint-resource-in-Azure-and-pair-it-with-a-LUIS-Application)
|
||||
|
||||
___
|
||||
|
||||
## [Prerequisites](#Table-of-Contents):
|
||||
|
||||
#### Install Azure CLI >=2.0.61:
|
||||
|
||||
Visit the following page to find the correct installer for your OS:
|
||||
- https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
|
||||
|
||||
#### Install LUIS CLI >=2.4.0:
|
||||
|
||||
Open a CLI of your choice and type the following:
|
||||
|
||||
```bash
|
||||
npm i -g luis-apis@^2.4.0
|
||||
```
|
||||
|
||||
#### LUIS portal account:
|
||||
|
||||
You should already have a LUIS account with either https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. To determine where to create a LUIS account, consider where you will deploy your LUIS applications, and then place them in [the corresponding region][LUIS-Authoring-Regions].
|
||||
|
||||
After you've created your account, you need your [Authoring Key][LUIS-AKey] and a LUIS application ID.
|
||||
|
||||
[LUIS-Authoring-Regions]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-reference-regions#luis-authoring-regions]
|
||||
[LUIS-AKey]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-concept-keys#authoring-key
|
||||
|
||||
___
|
||||
|
||||
## [Import a new LUIS Application using a local LUIS application](#Table-of-Contents)
|
||||
|
||||
### 1. Import the local LUIS application to luis.ai
|
||||
|
||||
```bash
|
||||
luis import application --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appName "FlightBooking" --in "./cognitiveModels/FlightBooking.json"
|
||||
```
|
||||
|
||||
Outputs the following JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "########-####-####-####-############",
|
||||
"name": "FlightBooking",
|
||||
"description": "A LUIS model that uses intent and entities.",
|
||||
"culture": "en-us",
|
||||
"usageScenario": "",
|
||||
"domain": "",
|
||||
"versionsCount": 1,
|
||||
"createdDateTime": "2019-03-29T18:32:02Z",
|
||||
"endpoints": {},
|
||||
"endpointHitsCount": 0,
|
||||
"activeVersion": "0.1",
|
||||
"ownerEmail": "bot@contoso.com",
|
||||
"tokenizerVersion": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
For the next step, you'll need the `"id"` value for `--appId` and the `"activeVersion"` value for `--versionId`.
|
||||
|
||||
### 2. Train the LUIS Application
|
||||
|
||||
```bash
|
||||
luis train version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --wait
|
||||
```
|
||||
|
||||
### 3. Publish the LUIS Application
|
||||
|
||||
```bash
|
||||
luis publish version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --publishRegion "LuisAppPublishRegion"
|
||||
```
|
||||
|
||||
> `--region` corresponds to the region you _author_ your application in. The regions available for this are "westus", "westeurope" and "australiaeast". <br/>
|
||||
> These regions correspond to the three available portals, https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. <br/>
|
||||
> `--publishRegion` corresponds to the region of the endpoint you're publishing to, (e.g. "westus", "southeastasia", "westeurope", "brazilsouth"). <br/>
|
||||
> See the [reference docs][Endpoint-API] for a list of available publish/endpoint regions.
|
||||
|
||||
[Endpoint-API]: https://westus.dev.cognitive.microsoft.com/docs/services/5819c76f40a6350ce09de1ac/operations/5819c77140a63516d81aee78
|
||||
|
||||
Outputs the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"versionId": "0.1",
|
||||
"isStaging": false,
|
||||
"endpointUrl": "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/########-####-####-####-############",
|
||||
"region": "westus",
|
||||
"assignedEndpointKey": null,
|
||||
"endpointRegion": "westus",
|
||||
"failedRegions": "",
|
||||
"publishedDateTime": "2019-03-29T18:40:32Z",
|
||||
"directVersionPublish": false
|
||||
}
|
||||
```
|
||||
|
||||
To see how to create an LUIS Cognitive Service Resource in Azure, please see [the next README][README-LUIS]. This Resource should be used when you want to move your bot to production. The instructions will show you how to create and pair the resource with a LUIS Application.
|
||||
|
||||
[README-LUIS]: ./README-LUIS.md
|
||||
|
||||
___
|
||||
|
||||
## [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#Table-of-Contents)
|
||||
|
||||
### 1. Create a new LUIS Cognitive Services resource on Azure via Azure CLI
|
||||
|
||||
> _Note:_ <br/>
|
||||
> _If you don't have a Resource Group in your Azure subscription, you can create one through the Azure portal or through using:_
|
||||
> ```bash
|
||||
> az group create --subscription "AzureSubscriptionGuid" --location "westus" --name "ResourceGroupName"
|
||||
> ```
|
||||
> _To see a list of valid locations, use `az account list-locations`_
|
||||
|
||||
|
||||
```bash
|
||||
# Use Azure CLI to create the LUIS Key resource on Azure
|
||||
az cognitiveservices account create --kind "luis" --name "NewLuisResourceName" --sku "S0" --location "westus" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
|
||||
```
|
||||
|
||||
The command will output a response similar to the JSON below:
|
||||
|
||||
```json
|
||||
{
|
||||
"endpoint": "https://westus.api.cognitive.microsoft.com/luis/v2.0",
|
||||
"etag": "\"########-####-####-####-############\"",
|
||||
"id": "/subscriptions/########-####-####-####-############/resourceGroups/ResourceGroupName/providers/Microsoft.CognitiveServices/accounts/NewLuisResourceName",
|
||||
"internalId": "################################",
|
||||
"kind": "luis",
|
||||
"location": "westus",
|
||||
"name": "NewLuisResourceName",
|
||||
"provisioningState": "Succeeded",
|
||||
"resourceGroup": "ResourceGroupName",
|
||||
"sku": {
|
||||
"name": "S0",
|
||||
"tier": null
|
||||
},
|
||||
"tags": null,
|
||||
"type": "Microsoft.CognitiveServices/accounts"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Take the output from the previous command and create a JSON file in the following format:
|
||||
|
||||
```json
|
||||
{
|
||||
"azureSubscriptionId": "00000000-0000-0000-0000-000000000000",
|
||||
"resourceGroup": "ResourceGroupName",
|
||||
"accountName": "NewLuisResourceName"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Retrieve ARM access token via Azure CLI
|
||||
|
||||
```bash
|
||||
az account get-access-token --subscription "AzureSubscriptionGuid"
|
||||
```
|
||||
|
||||
This will return an object that looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "eyJ0eXAiOiJKVtokentokentokentokentokeng1dCI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyIsItokenI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUzODc3MTUwLCJuYmYiOjE1NTM4NzcxNTAsImV4cCI6MTU1Mzg4MTA1MCwiX2NsYWltX25hbWVzIjp7Imdyb3VwcyI6InNyYzEifSwiX2NsYWltX3NvdXJjZXMiOnsic3JjMSI6eyJlbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGgud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3VzZXJzL2ZmZTQyM2RkLWJhM2YtNDg0Ny04NjgyLWExNTI5MDA4MjM4Ny9nZXRNZW1iZXJPYmplY3RzIn19LCJhY3IiOiIxIiwiYWlvIjoiQVZRQXEvOEtBQUFBeGVUc201NDlhVHg4RE1mMFlRVnhGZmxxOE9RSC9PODR3QktuSmRqV1FqTkkwbmxLYzB0bHJEZzMyMFZ5bWZGaVVBSFBvNUFFUTNHL0FZNDRjdk01T3M0SEt0OVJkcE5JZW9WU0dzd0kvSkk9IiwiYW1yIjpbIndpYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImRldmljZWlkIjoiNDhmNDVjNjEtMTg3Zi00MjUxLTlmZWItMTllZGFkZmMwMmE3IiwiZmFtaWx5X25hbWUiOiJHdW0iLCJnaXZlbl9uYW1lIjoiU3RldmVuIiwiaXBhZGRyIjoiMTY3LjIyMC4yLjU1IiwibmFtZSI6IlN0ZXZlbiBHdW0iLCJvaWQiOiJmZmU0MjNkZC1iYTNmLTQ4NDctODY4Mi1hMTUyOTAwODIzODciLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtMjEyNzUyMTE4NC0xNjA0MDEyOTIwLTE4ODc5Mjc1MjctMjYwOTgyODUiLCJwdWlkIjoiMTAwMzdGRkVBMDQ4NjlBNyIsInJoIjoiSSIsInNjcCI6InVzZXJfaW1wZXJzb25hdGlvbiIsInN1YiI6Ik1rMGRNMWszN0U5ckJyMjhieUhZYjZLSU85LXVFQVVkZFVhNWpkSUd1Nk0iLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InN0Z3VtQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJzdGd1bUBtaWNyb3NvZnQuY29tIiwidXRpIjoiT2w2NGN0TXY4RVNEQzZZQWRqRUFtokenInZlciI6IjEuMCJ9.kFAsEilE0mlS1pcpqxf4rEnRKeYsehyk-gz-zJHUrE__oad3QjgDSBDPrR_ikLdweynxbj86pgG4QFaHURNCeE6SzrbaIrNKw-n9jrEtokenlosOxg_0l2g1LeEUOi5Q4gQREAU_zvSbl-RY6sAadpOgNHtGvz3Rc6FZRITfkckSLmsKAOFoh-aWC6tFKG8P52rtB0qVVRz9tovBeNqkMYL49s9ypduygbXNVwSQhm5JszeWDgrFuVFHBUP_iENCQYGQpEZf_KvjmX1Ur1F9Eh9nb4yI2gFlKncKNsQl-tokenK7-tokentokentokentokentokentokenatoken",
|
||||
"expiresOn": "2200-12-31 23:59:59.999999",
|
||||
"subscription": "AzureSubscriptionGuid",
|
||||
"tenant": "tenant-guid",
|
||||
"tokenType": "Bearer"
|
||||
}
|
||||
```
|
||||
|
||||
The value needed for the next step is the `"accessToken"`.
|
||||
|
||||
### 3. Use `luis add appazureaccount` to pair your LUIS resource with a LUIS Application
|
||||
|
||||
```bash
|
||||
luis add appazureaccount --in "path/to/created/requestBody.json" --appId "LuisAppId" --authoringKey "LuisAuthoringKey" --armToken "accessToken"
|
||||
```
|
||||
|
||||
If successful, it should yield a response like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "Success",
|
||||
"message": "Operation Successful"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. See the LUIS Cognitive Services' keys
|
||||
|
||||
```bash
|
||||
az cognitiveservices account keys list --name "NewLuisResourceName" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
|
||||
```
|
||||
|
||||
This will return an object that looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"key1": "9a69####dc8f####8eb4####399f####",
|
||||
"key2": "####f99e####4b1a####fb3b####6b9f"
|
||||
}
|
||||
```
|
|
@ -1,4 +1,4 @@
|
|||
# core-bot
|
||||
# CoreBot
|
||||
|
||||
Bot Framework v4 core bot sample.
|
||||
|
||||
|
@ -70,7 +70,7 @@ LuisAPIHostName = "Your LUIS App region here (i.e: westus.api.cognitive.microsof
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ class MainDialog extends ComponentDialog {
|
|||
}
|
||||
|
||||
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
|
||||
const messageText = stepContext.options.restartMsg ? stepContext.options.restartMsg : `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`;
|
||||
const messageText = stepContext.options.restartMsg ? stepContext.options.restartMsg : `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`;
|
||||
const promptMessage = MessageFactory.text(messageText, messageText, InputHints.ExpectingInput);
|
||||
return await stepContext.prompt('TextPrompt', { prompt: promptMessage });
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@microsoft/recognizers-text-data-types-timex-expression": "1.1.4",
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-ai": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder-testing": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-ai": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"botbuilder-testing": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -86,7 +86,7 @@ describe('MainDialog', () => {
|
|||
|
||||
const reply = await client.sendActivity('hi');
|
||||
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
|
||||
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`, 'Did not show prompt');
|
||||
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`, 'Did not show prompt');
|
||||
});
|
||||
|
||||
describe('Invokes tasks based on LUIS intent', () => {
|
||||
|
@ -110,7 +110,7 @@ describe('MainDialog', () => {
|
|||
console.log(`Test Case: ${ testData.intent }`);
|
||||
let reply = await client.sendActivity('Hi');
|
||||
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
|
||||
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`);
|
||||
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`);
|
||||
|
||||
reply = await client.sendActivity(testData.utterance);
|
||||
assert.strictEqual(reply.text, testData.invokedDialogResponse);
|
||||
|
@ -150,7 +150,7 @@ describe('MainDialog', () => {
|
|||
console.log(`Test Case: ${ mockLuisResult.text }`);
|
||||
let reply = await client.sendActivity('Hi');
|
||||
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
|
||||
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`);
|
||||
assert.strictEqual(reply.text, `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`);
|
||||
|
||||
reply = await client.sendActivity(mockLuisResult.text);
|
||||
assert.strictEqual(reply.text, testData.expectedMessage);
|
||||
|
|
|
@ -63,7 +63,7 @@ To learn how to configure Dispatch with multiple LUIS models and QnA Maker servi
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -71,9 +71,9 @@ To learn how to configure Dispatch with multiple LUIS models and QnA Maker servi
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Dispatch
|
||||
## Interacting with the bot
|
||||
|
||||
Once you are confortable with the concepts presented in this sample, you may want to configure Dispatch using a CLI tool. [Dispatch CLI](https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Dispatch) is a CLI tool that enables you to create a dispatch NLP model across the different LUIS applications and/ or QnA Maker Knowledge Bases you have for your bot.
|
||||
Once you are comfortable with the concepts presented in this sample, you may want to configure Dispatch using a CLI tool. [Dispatch CLI](https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Dispatch) is a CLI tool that enables you to create a dispatch NLP model across the different LUIS applications and/ or QnA Maker Knowledge Bases you have for your bot.
|
||||
|
||||
## Deploy the bot to Azure
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
|
||||
// Note: Ensure you have a .env file and include all necessary credentials to access services like LUIS and QnAMaker.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -13,10 +18,6 @@ const { BotFrameworkAdapter } = require('botbuilder');
|
|||
|
||||
const { DispatchBot } = require('./bots/dispatchBot');
|
||||
|
||||
// Note: Ensure you have a .env file and include all necessary credentials to access services like LUIS and QnAMaker.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-ai": "~4.9.1",
|
||||
"botbuilder-azure": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-ai": "~4.10.1",
|
||||
"botbuilder-azure": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# handling attachments
|
||||
# Handling Attachments
|
||||
|
||||
Bot Framework v4 handling attachments bot sample
|
||||
|
||||
|
@ -46,7 +46,7 @@ upload files to Teams from a bot and how to receive a file sent to a bot as an a
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -54,7 +54,7 @@ upload files to Teams from a bot and how to receive a file sent to a bot as an a
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Attachments
|
||||
## Interacting with the bot
|
||||
|
||||
A message exchange between user and bot may contain cards and media attachments, such as images, video, audio, and files.
|
||||
The types of attachments that may be sent and received varies by channel. Additionally, a bot may also receive file attachments.
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, './.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -10,10 +15,6 @@ const { BotFrameworkAdapter } = require('botbuilder');
|
|||
|
||||
const { AttachmentsBot } = require('./bots/attachmentsBot');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, './.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter. See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: process.env.MicrosoftAppID,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# proactive messages
|
||||
# Proactive Messages
|
||||
|
||||
Bot Framework v4 proactive messages bot sample
|
||||
|
||||
|
@ -78,7 +78,7 @@ With the Bot Framework Emulator connected to your running bot, the sample will n
|
|||
- Navigate to `http://localhost:3978/api/notify`
|
||||
- Using the Bot Framwork Emulator, notice a message was proactively sent to the user from the bot.
|
||||
|
||||
## Proactive Messages
|
||||
## Interacting with the bots
|
||||
|
||||
In addition to responding to incoming messages, bots are frequently called on to send "proactive" messages based on activity, scheduled tasks, or external events.
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
|
||||
// Note: Ensure you have a .env file and include the MicrosoftAppId and MicrosoftAppPassword.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -14,10 +19,6 @@ const { BotFrameworkAdapter } = require('botbuilder');
|
|||
// This bot's main dialog.
|
||||
const { ProactiveBot } = require('./bots/proactiveBot');
|
||||
|
||||
// Note: Ensure you have a .env file and include the MicrosoftAppId and MicrosoftAppPassword.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"fetch-ponyfill": "^6.1.0",
|
||||
"moment": "^2.26.0",
|
||||
|
|
|
@ -73,7 +73,7 @@ This sample **requires** prerequisites in order to run.
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required packages.
|
||||
const path = require('path');
|
||||
|
||||
// Note: Ensure you have a .env file and include translatorKey.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
const { MicrosoftTranslator } = require('./translation/microsoftTranslator');
|
||||
const { TranslatorMiddleware } = require('./translation/translatorMiddleware');
|
||||
|
@ -16,10 +21,6 @@ const { BotFrameworkAdapter, MemoryStorage, UserState, ActivityTypes, TurnContex
|
|||
// This bot's main dialog.
|
||||
const { MultilingualBot } = require('./bots/multilingualBot');
|
||||
|
||||
// Note: Ensure you have a .env file and include translatorKey.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Used to create the BotStatePropertyAccessor for storing the user's language preference.
|
||||
const LANGUAGE_PREFERENCE = 'language_preference';
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"restify": "~8.5.1"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# bot authentication
|
||||
# Bot Authentication
|
||||
|
||||
Bot Framework v4 bot authentication sample
|
||||
|
||||
|
@ -6,6 +6,8 @@ This bot has been created using [Bot Framework](https://dev.botframework.com), i
|
|||
|
||||
The sample uses the bot authentication capabilities in [Azure Bot Service](https://docs.botframework.com), providing features to make it easier to develop a bot that authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, etc.
|
||||
|
||||
NOTE: Microsoft Teams currently differs slightly in the way auth is integrated with the bot. Refer to sample 46.teams-auth.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Node.js](https://nodejs.org) version 10.14 or higher
|
||||
|
@ -45,15 +47,15 @@ After Authentication has been configured via Azure Bot Service, you can test the
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
- Launch Bot Framework Emulator
|
||||
- File -> Open Bot
|
||||
- Enter a Bot URL of `https://<YOUR_BOTS_URI_ON_AZURE>`
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Authentication
|
||||
## Interacting with the bot
|
||||
|
||||
This sample uses bot authentication capabilities in Azure Bot Service, providing features to make it easier to develop a bot that authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, etc. These updates also take steps towards an improved user experience by eliminating the magic code verification for some clients.
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required pckages
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -14,10 +19,6 @@ const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = req
|
|||
const { AuthBot } = require('./bots/authBot');
|
||||
const { MainDialog } = require('./dialogs/mainDialog');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# custom dialogs
|
||||
# Custom Dialogs
|
||||
|
||||
Bot Framework v4 custom dialogs bot sample
|
||||
|
||||
|
@ -45,7 +45,7 @@ BotFramework provides a built-in base class called `Dialog`. By subclassing `Dia
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
@ -53,7 +53,7 @@ BotFramework provides a built-in base class called `Dialog`. By subclassing `Dia
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Custom Dialogs
|
||||
## Interacting with the bot
|
||||
|
||||
BotFramework provides a built-in base class called `Dialog`. By subclassing Dialog, developers
|
||||
can create new ways to define and control dialog flows used by the bot. By adhering to the
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
const restify = require('restify');
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Import required bot services.
|
||||
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
|
||||
const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = require('botbuilder');
|
||||
|
@ -11,10 +15,6 @@ const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = req
|
|||
const { DialogBot } = require('./bots/dialogBot');
|
||||
const { RootDialog } = require('./dialogs/rootDialog');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create HTTP server.
|
||||
const server = restify.createServer();
|
||||
server.listen(process.env.port || process.env.PORT || 3978, function() {
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
# Setting up LUIS via CLI:
|
||||
|
||||
This README contains information on how to create and deploy a LUIS application. When the bot is ready to be deployed to production, we recommend creating a LUIS Endpoint Resource for usage with your LUIS App.
|
||||
|
||||
> _For instructions on how to create a LUIS Application via the LUIS portal, see these Quickstart steps:_
|
||||
> 1. _[Quickstart: Create a new app in the LUIS portal][Quickstart-create]_
|
||||
> 2. _[Quickstart: Deploy an app in the LUIS portal][Quickstart-deploy]_
|
||||
|
||||
[Quickstart-create]: https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-build-app
|
||||
[Quickstart-deploy]:https://docs.microsoft.com/azure/cognitive-services/luis/get-started-portal-deploy-app
|
||||
|
||||
## Table of Contents:
|
||||
|
||||
- [Prerequisites](#Prerequisites)
|
||||
- [Import a new LUIS Application using a local LUIS application](#Import-a-new-LUIS-Application-using-a-local-LUIS-application)
|
||||
- [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#How-to-create-a-LUIS-Endpoint-resource-in-Azure-and-pair-it-with-a-LUIS-Application)
|
||||
|
||||
___
|
||||
|
||||
## [Prerequisites](#Table-of-Contents):
|
||||
|
||||
#### Install Azure CLI >=2.0.61:
|
||||
|
||||
Visit the following page to find the correct installer for your OS:
|
||||
- https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
|
||||
|
||||
#### Install LUIS CLI >=2.4.0:
|
||||
|
||||
Open a CLI of your choice and type the following:
|
||||
|
||||
```bash
|
||||
npm i -g luis-apis@^2.4.0
|
||||
```
|
||||
|
||||
#### LUIS portal account:
|
||||
|
||||
You should already have a LUIS account with either https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. To determine where to create a LUIS account, consider where you will deploy your LUIS applications, and then place them in [the corresponding region][LUIS-Authoring-Regions].
|
||||
|
||||
After you've created your account, you need your [Authoring Key][LUIS-AKey] and a LUIS application ID.
|
||||
|
||||
[LUIS-Authoring-Regions]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-reference-regions#luis-authoring-regions]
|
||||
[LUIS-AKey]: https://docs.microsoft.com/azure/cognitive-services/luis/luis-concept-keys#authoring-key
|
||||
|
||||
___
|
||||
|
||||
## [Import a new LUIS Application using a local LUIS application](#Table-of-Contents)
|
||||
|
||||
### 1. Import the local LUIS application to luis.ai
|
||||
|
||||
```bash
|
||||
luis import application --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appName "FlightBooking" --in "./cognitiveModels/FlightBooking.json"
|
||||
```
|
||||
|
||||
Outputs the following JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "########-####-####-####-############",
|
||||
"name": "FlightBooking",
|
||||
"description": "A LUIS model that uses intent and entities.",
|
||||
"culture": "en-us",
|
||||
"usageScenario": "",
|
||||
"domain": "",
|
||||
"versionsCount": 1,
|
||||
"createdDateTime": "2019-03-29T18:32:02Z",
|
||||
"endpoints": {},
|
||||
"endpointHitsCount": 0,
|
||||
"activeVersion": "0.1",
|
||||
"ownerEmail": "bot@contoso.com",
|
||||
"tokenizerVersion": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
For the next step, you'll need the `"id"` value for `--appId` and the `"activeVersion"` value for `--versionId`.
|
||||
|
||||
### 2. Train the LUIS Application
|
||||
|
||||
```bash
|
||||
luis train version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --wait
|
||||
```
|
||||
|
||||
### 3. Publish the LUIS Application
|
||||
|
||||
```bash
|
||||
luis publish version --region "LuisAppAuthoringRegion" --authoringKey "LuisAuthoringKey" --appId "LuisAppId" --versionId "LuisAppversion" --publishRegion "LuisAppPublishRegion"
|
||||
```
|
||||
|
||||
> `--region` corresponds to the region you _author_ your application in. The regions available for this are "westus", "westeurope" and "australiaeast". <br/>
|
||||
> These regions correspond to the three available portals, https://luis.ai, https://eu.luis.ai, or https://au.luis.ai. <br/>
|
||||
> `--publishRegion` corresponds to the region of the endpoint you're publishing to, (e.g. "westus", "southeastasia", "westeurope", "brazilsouth"). <br/>
|
||||
> See the [reference docs][Endpoint-API] for a list of available publish/endpoint regions.
|
||||
|
||||
[Endpoint-API]: https://westus.dev.cognitive.microsoft.com/docs/services/5819c76f40a6350ce09de1ac/operations/5819c77140a63516d81aee78
|
||||
|
||||
Outputs the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"versionId": "0.1",
|
||||
"isStaging": false,
|
||||
"endpointUrl": "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/########-####-####-####-############",
|
||||
"region": "westus",
|
||||
"assignedEndpointKey": null,
|
||||
"endpointRegion": "westus",
|
||||
"failedRegions": "",
|
||||
"publishedDateTime": "2019-03-29T18:40:32Z",
|
||||
"directVersionPublish": false
|
||||
}
|
||||
```
|
||||
|
||||
To see how to create an LUIS Cognitive Service Resource in Azure, please see [the next README][README-LUIS]. This Resource should be used when you want to move your bot to production. The instructions will show you how to create and pair the resource with a LUIS Application.
|
||||
|
||||
[README-LUIS]: ./README-LUIS.md
|
||||
|
||||
___
|
||||
|
||||
## [How to create a LUIS Endpoint resource in Azure and pair it with a LUIS Application](#Table-of-Contents)
|
||||
|
||||
### 1. Create a new LUIS Cognitive Services resource on Azure via Azure CLI
|
||||
|
||||
> _Note:_ <br/>
|
||||
> _If you don't have a Resource Group in your Azure subscription, you can create one through the Azure portal or through using:_
|
||||
> ```bash
|
||||
> az group create --subscription "AzureSubscriptionGuid" --location "westus" --name "ResourceGroupName"
|
||||
> ```
|
||||
> _To see a list of valid locations, use `az account list-locations`_
|
||||
|
||||
|
||||
```bash
|
||||
# Use Azure CLI to create the LUIS Key resource on Azure
|
||||
az cognitiveservices account create --kind "luis" --name "NewLuisResourceName" --sku "S0" --location "westus" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
|
||||
```
|
||||
|
||||
The command will output a response similar to the JSON below:
|
||||
|
||||
```json
|
||||
{
|
||||
"endpoint": "https://westus.api.cognitive.microsoft.com/luis/v2.0",
|
||||
"etag": "\"########-####-####-####-############\"",
|
||||
"id": "/subscriptions/########-####-####-####-############/resourceGroups/ResourceGroupName/providers/Microsoft.CognitiveServices/accounts/NewLuisResourceName",
|
||||
"internalId": "################################",
|
||||
"kind": "luis",
|
||||
"location": "westus",
|
||||
"name": "NewLuisResourceName",
|
||||
"provisioningState": "Succeeded",
|
||||
"resourceGroup": "ResourceGroupName",
|
||||
"sku": {
|
||||
"name": "S0",
|
||||
"tier": null
|
||||
},
|
||||
"tags": null,
|
||||
"type": "Microsoft.CognitiveServices/accounts"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Take the output from the previous command and create a JSON file in the following format:
|
||||
|
||||
```json
|
||||
{
|
||||
"azureSubscriptionId": "00000000-0000-0000-0000-000000000000",
|
||||
"resourceGroup": "ResourceGroupName",
|
||||
"accountName": "NewLuisResourceName"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Retrieve ARM access token via Azure CLI
|
||||
|
||||
```bash
|
||||
az account get-access-token --subscription "AzureSubscriptionGuid"
|
||||
```
|
||||
|
||||
This will return an object that looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "eyJ0eXAiOiJKVtokentokentokentokentokeng1dCI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyIsItokenI6Ik4tbEMwbi05REFMcXdodUhZbkhRNjNHZUNYYyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNTUzODc3MTUwLCJuYmYiOjE1NTM4NzcxNTAsImV4cCI6MTU1Mzg4MTA1MCwiX2NsYWltX25hbWVzIjp7Imdyb3VwcyI6InNyYzEifSwiX2NsYWltX3NvdXJjZXMiOnsic3JjMSI6eyJlbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGgud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3VzZXJzL2ZmZTQyM2RkLWJhM2YtNDg0Ny04NjgyLWExNTI5MDA4MjM4Ny9nZXRNZW1iZXJPYmplY3RzIn19LCJhY3IiOiIxIiwiYWlvIjoiQVZRQXEvOEtBQUFBeGVUc201NDlhVHg4RE1mMFlRVnhGZmxxOE9RSC9PODR3QktuSmRqV1FqTkkwbmxLYzB0bHJEZzMyMFZ5bWZGaVVBSFBvNUFFUTNHL0FZNDRjdk01T3M0SEt0OVJkcE5JZW9WU0dzd0kvSkk9IiwiYW1yIjpbIndpYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImRldmljZWlkIjoiNDhmNDVjNjEtMTg3Zi00MjUxLTlmZWItMTllZGFkZmMwMmE3IiwiZmFtaWx5X25hbWUiOiJHdW0iLCJnaXZlbl9uYW1lIjoiU3RldmVuIiwiaXBhZGRyIjoiMTY3LjIyMC4yLjU1IiwibmFtZSI6IlN0ZXZlbiBHdW0iLCJvaWQiOiJmZmU0MjNkZC1iYTNmLTQ4NDctODY4Mi1hMTUyOTAwODIzODciLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtMjEyNzUyMTE4NC0xNjA0MDEyOTIwLTE4ODc5Mjc1MjctMjYwOTgyODUiLCJwdWlkIjoiMTAwMzdGRkVBMDQ4NjlBNyIsInJoIjoiSSIsInNjcCI6InVzZXJfaW1wZXJzb25hdGlvbiIsInN1YiI6Ik1rMGRNMWszN0U5ckJyMjhieUhZYjZLSU85LXVFQVVkZFVhNWpkSUd1Nk0iLCJ0aWQiOiI3MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDciLCJ1bmlxdWVfbmFtZSI6InN0Z3VtQG1pY3Jvc29mdC5jb20iLCJ1cG4iOiJzdGd1bUBtaWNyb3NvZnQuY29tIiwidXRpIjoiT2w2NGN0TXY4RVNEQzZZQWRqRUFtokenInZlciI6IjEuMCJ9.kFAsEilE0mlS1pcpqxf4rEnRKeYsehyk-gz-zJHUrE__oad3QjgDSBDPrR_ikLdweynxbj86pgG4QFaHURNCeE6SzrbaIrNKw-n9jrEtokenlosOxg_0l2g1LeEUOi5Q4gQREAU_zvSbl-RY6sAadpOgNHtGvz3Rc6FZRITfkckSLmsKAOFoh-aWC6tFKG8P52rtB0qVVRz9tovBeNqkMYL49s9ypduygbXNVwSQhm5JszeWDgrFuVFHBUP_iENCQYGQpEZf_KvjmX1Ur1F9Eh9nb4yI2gFlKncKNsQl-tokenK7-tokentokentokentokentokentokenatoken",
|
||||
"expiresOn": "2200-12-31 23:59:59.999999",
|
||||
"subscription": "AzureSubscriptionGuid",
|
||||
"tenant": "tenant-guid",
|
||||
"tokenType": "Bearer"
|
||||
}
|
||||
```
|
||||
|
||||
The value needed for the next step is the `"accessToken"`.
|
||||
|
||||
### 3. Use `luis add appazureaccount` to pair your LUIS resource with a LUIS Application
|
||||
|
||||
```bash
|
||||
luis add appazureaccount --in "path/to/created/requestBody.json" --appId "LuisAppId" --authoringKey "LuisAuthoringKey" --armToken "accessToken"
|
||||
```
|
||||
|
||||
If successful, it should yield a response like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "Success",
|
||||
"message": "Operation Successful"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. See the LUIS Cognitive Services' keys
|
||||
|
||||
```bash
|
||||
az cognitiveservices account keys list --name "NewLuisResourceName" --subscription "AzureSubscriptionGuid" -g "ResourceGroupName"
|
||||
```
|
||||
|
||||
This will return an object that looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"key1": "9a69####dc8f####8eb4####399f####",
|
||||
"key2": "####f99e####4b1a####fb3b####6b9f"
|
||||
}
|
||||
```
|
|
@ -76,7 +76,7 @@ Application Insights resource creation steps can be found [here](https://docs.mi
|
|||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class MainDialog extends ComponentDialog {
|
|||
return await stepContext.next();
|
||||
}
|
||||
const weekLaterDate = moment().add(7, 'days').format('MMMM D, YYYY');
|
||||
const messageText = stepContext.options.restartMsg ? stepContext.options.restartMsg : `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${weekLaterDate}"`;
|
||||
const messageText = stepContext.options.restartMsg ? stepContext.options.restartMsg : `What can I help you with today?\nSay something like "Book a flight from Paris to Berlin on ${ weekLaterDate }"`;
|
||||
const promptMessage = MessageFactory.text(messageText, messageText, InputHints.ExpectingInput);
|
||||
return await stepContext.prompt('TextPrompt', { prompt: promptMessage });
|
||||
}
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
|
||||
// Note: Ensure you have a .env file and include LuisAppId, LuisAPIKey and LuisAPIHostName.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required services for bot telemetry
|
||||
|
@ -23,10 +28,6 @@ const { MainDialog } = require('./dialogs/mainDialog');
|
|||
const { BookingDialog } = require('./dialogs/bookingDialog');
|
||||
const BOOKING_DIALOG = 'bookingDialog';
|
||||
|
||||
// Note: Ensure you have a .env file and include LuisAppId, LuisAPIKey and LuisAPIHostName.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
"author": "Microsoft",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@microsoft/recognizers-text-data-types-timex-expression": "~1.3.0",
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-ai": "~4.9.1",
|
||||
"botbuilder-applicationinsights": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"@microsoft/recognizers-text-data-types-timex-expression": "1.1.4",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-ai": "~4.10.1",
|
||||
"botbuilder-applicationinsights": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"path": "^0.12.7",
|
||||
"restify": "~8.5.1"
|
||||
|
|
|
@ -49,8 +49,7 @@ More information about configuring a bot for Facebook Messenger can be found her
|
|||
|
||||
[Microsoft Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework emulator from [here](https://github.com/microsoft/botframework-emulator/releases)
|
||||
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to bot using Bot Framework Emulator
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required packages
|
||||
const path = require('path');
|
||||
|
||||
// Note: Ensure that you have a MicrosoftAppId and MicrosoftAppPassword added to the .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -13,10 +18,6 @@ const { BotFrameworkAdapter } = require('botbuilder');
|
|||
|
||||
const { FacebookBot } = require('./bots/facebookBot');
|
||||
|
||||
// Note: Ensure that you have a MicrosoftAppId and MicrosoftAppPassword added to the .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -53,7 +53,7 @@ application setup for use in Azure Bot Service. The [scopes](https://developer.m
|
|||
|
||||
[Microsoft Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator from [here](https://github.com/microsoft/botframework-emulator/releases)
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
- In Bot Framework Emulator Settings, enable `Use a sign-in verification code for OAuthCards` to receive the magic code
|
||||
|
||||
### Connect to bot using Bot Framework Emulator
|
||||
|
@ -62,7 +62,7 @@ application setup for use in Azure Bot Service. The [scopes](https://developer.m
|
|||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages
|
||||
|
||||
## Authentication
|
||||
## Interacting with the bot
|
||||
|
||||
This sample uses the bot authentication capabilities of Azure Bot Service, providing features to make it easier to develop a bot that
|
||||
authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, and so on. These updates also
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Note: Ensure you have a .env file and include MicrosoftAppId and MicrosoftAppPassword.
|
||||
// This MicrosoftApp should have OAuth enabled.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -11,11 +17,6 @@ const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = req
|
|||
const { AuthBot } = require('./bots/authBot');
|
||||
const { MainDialog } = require('./dialogs/mainDialog');
|
||||
|
||||
// Note: Ensure you have a .env file and include MicrosoftAppId and MicrosoftAppPassword.
|
||||
// This MicrosoftApp should have OAuth enabled.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create the adapter. See https://aka.ms/about-bot-adapter to learn more adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: process.env.MicrosoftAppId,
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@microsoft/microsoft-graph-client": "~2.0.0",
|
||||
"botbuilder": "~4.9.2",
|
||||
"botbuilder-dialogs": "~4.9.2",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required pckages
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -14,10 +19,6 @@ const { BotFrameworkAdapter, MemoryStorage } = require('botbuilder');
|
|||
const { ActivityLog } = require('./activityLog');
|
||||
const { MessageReactionBot } = require('./bots/messageReactionBot');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -103,7 +103,7 @@ The use of X to blank out the characters is also applies to the representation o
|
|||
XXXX-WXX-1
|
||||
```
|
||||
|
||||
Here XXXX means *any* year and WXX means *any* week, so what remains is the day component. And with the ISO week starting on a Monday and indexing from 1 we get Monday.
|
||||
Here XXXX means *any* year and WXX means *any* week, so what remains is the day component. And with the ISO week starting on a Monday and indexing from 1 we get Monday.
|
||||
|
||||
The Text.Recognizers are written to attempt to resolve to a specific date if they can. This can result in some surprisingly subtle behavior. For exampe, if we had said "this Monday" it would have resolved to a specific date such as this:
|
||||
|
||||
|
@ -158,7 +158,7 @@ PT4H
|
|||
|
||||
Given the nature of the problem and the fact that decimal is supported, means there are many different ways to express the same duration, for example PT0.5H is the same as PT30M just as P1W is the same as P7D. The Text.Recognizers make no attempt to normalize such things, instead they just try to render the original natural language utterance as directly as possible. The Text.Recognizers also don't try to merge separate durations they find in the input. For example, the text "4 hours 30 minutes" will result in two results.
|
||||
|
||||
## Representing Ranges
|
||||
## Representing Ranges
|
||||
|
||||
### Date Ranges
|
||||
|
||||
|
|
|
@ -1,7 +1,53 @@
|
|||
# complex dialog sample
|
||||
# Complex Dialog Sample
|
||||
|
||||
This sample creates a complex conversation with dialogs.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Node.js](https://nodejs.org) version 10.14 or higher
|
||||
|
||||
```bash
|
||||
# determine node version
|
||||
node --version
|
||||
```
|
||||
|
||||
## To try this sample
|
||||
|
||||
- Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/microsoft/botbuilder-samples.git
|
||||
```
|
||||
|
||||
- In a terminal, navigate to `samples/javascript_nodejs/43.complex-dialog`
|
||||
|
||||
```bash
|
||||
cd samples/javascript_nodejs43.complex-dialog
|
||||
```
|
||||
|
||||
- Install modules
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
- Start the bot
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
## Testing the bot using Bot Framework Emulator
|
||||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
- Launch Bot Framework Emulator
|
||||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Further reading
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -11,10 +16,6 @@ const { BotFrameworkAdapter, MemoryStorage, UserState, ConversationState } = req
|
|||
const { DialogAndWelcomeBot } = require('./bots/dialogAndWelcomeBot');
|
||||
const { MainDialog } = require('./dialogs/mainDialog');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create HTTP server
|
||||
const server = restify.createServer();
|
||||
server.listen(process.env.port || process.env.PORT || 3978, function() {
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
# Prompt users for input
|
||||
|
||||
This bot has been created using [Bot Framework][1], it shows how to:
|
||||
|
||||
- Maintain conversation state to track and direct the conversation and ask the user questions
|
||||
- Maintain user state to track the user's answers
|
||||
This sample demonstrates how to create your own prompts with an ASP.Net Core 2 bot.
|
||||
The bot maintains conversation state to track and direct the conversation and ask the user questions.
|
||||
The bot maintains user state to track the user's answers.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -40,7 +39,19 @@ This bot has been created using [Bot Framework][1], it shows how to:
|
|||
npm start
|
||||
```
|
||||
|
||||
## Bot state
|
||||
## Testing the bot using Bot Framework Emulator
|
||||
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
- Launch Bot Framework Emulator
|
||||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Interacting with the bot
|
||||
|
||||
A bot is inherently stateless. Once your bot is deployed, it may not run in the same process or on the same machine from one turn to the next.
|
||||
However, your bot may need to track the context of a conversation, so that it can manage its behavior and remember answers to previous questions.
|
||||
|
@ -52,22 +63,6 @@ In this example, the bot's state is used to a track number of messages.
|
|||
|
||||
This sample is intended to be run and tested locally and is not designed to be deployed to Azure.
|
||||
|
||||
## Testing the bot using Bot Framework Emulator
|
||||
|
||||
[Bot Framework Emulator][5] is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here][6]
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
- Launch Bot Framework Emulator
|
||||
- File -> Open Bot
|
||||
- Enter a Bot URL of `http://localhost:3978/api/messages`
|
||||
|
||||
## Deploy the bot to Azure
|
||||
|
||||
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure][40] for a complete list of deployment instructions.
|
||||
|
||||
## Further reading
|
||||
|
||||
- [Bot Framework Documentation][20]
|
||||
|
@ -75,8 +70,6 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure][40]
|
|||
- [Azure Bot Service Introduction][21]
|
||||
- [Azure Bot Service Documentation][22]
|
||||
- [Deploying Your Bot to Azure][40]
|
||||
- [Azure CLI][7]
|
||||
- [Azure Portal][10]
|
||||
- [Language Understanding using LUIS][11]
|
||||
- [Add Natural Language Understanding to Your Bot][12]
|
||||
- [TypeScript][2]
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -11,10 +16,6 @@ const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = req
|
|||
// This bot's main dialog.
|
||||
const { CustomPromptBot } = require('./bots/customPromptBot');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create HTTP server
|
||||
const server = restify.createServer();
|
||||
server.listen(process.env.port || process.env.PORT || 3978, function() {
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/recognizers-text-suite": "~1.3.0",
|
||||
"botbuilder": "~4.9.1",
|
||||
"@microsoft/recognizers-text-suite": "1.1.4",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -41,9 +41,9 @@ The bot maintains user state to track the user's answers.
|
|||
|
||||
## Testing the bot using Bot Framework Emulator
|
||||
|
||||
[Bot Framework Emulator][5] is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
|
||||
|
||||
- Install the Bot Framework Emulator version 4.9.0 or greater from [here][6]
|
||||
- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
|
||||
|
||||
### Connect to the bot using Bot Framework Emulator
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -11,10 +16,6 @@ const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = req
|
|||
// This bot's main dialog.
|
||||
const { StateManagementBot } = require('./bots/stateManagementBot');
|
||||
|
||||
// Read environment variables from .env file
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create HTTP server
|
||||
const server = restify.createServer();
|
||||
server.listen(process.env.port || process.env.PORT || 3978, function() {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
# teams-auth bot
|
||||
# Teams Auth Bot
|
||||
|
||||
Bot Framework v4 bot using Teams authentication
|
||||
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to get started with building a bot for Teams.
|
||||
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to get started with authentication in a bot for Microsoft Teams.
|
||||
|
||||
At this stage the primary focus of this sample is how to use the Bot Framework support for oauth in your bot. The reason for prioritizing this is that Teams behaves slightly differently than other channels in this regard. Specifically an Invoke Activity is sent to the bot rather than the Event Activity used by other channels. _This Invoke Activity must be forwarded to the dialog if the OAuthPrompt is being used._ This is done by subclassing the TeamsActivityHandler and implementing handleTeamsSigninVerifyState.
|
||||
The focus of this sample is how to use the Bot Framework support for oauth in your bot. Teams behaves slightly differently than other channels in this regard. Specifically an Invoke Activity is sent to the bot rather than the Event Activity used by other channels. _This Invoke Activity must be forwarded to the dialog if the OAuthPrompt is being used._ This is done by subclassing the ActivityHandler and this sample includes a reusable TeamsActivityHandler. This class is a candidate for future inclusion in the Bot Framework SDK.
|
||||
|
||||
The sample uses the bot authentication capabilities in [Azure Bot Service](https://docs.botframework.com), providing features to make it easier to develop a bot that authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, etc.
|
||||
The sample uses the bot authentication capabilities in [Azure Bot Service](https://docs.botframework.com), providing features to make it easier to develop a bot that authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, etc. The OAuth token is then used to make basic Microsoft Graph queries.
|
||||
|
||||
> IMPORTANT: The manifest file in this app adds "token.botframework.com" to the list of `validDomains`. This must be included in any bot that uses the Bot Framework OAuth flow.
|
||||
|
||||
See [install-and-test-the-bot-in-teams](https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/add-authentication#install-and-test-the-bot-in-teams)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Microsoft Teams is installed and you have an account (not a guest account)
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
// Import required pckages
|
||||
const path = require('path');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
const restify = require('restify');
|
||||
|
||||
// Import required bot services.
|
||||
|
@ -14,10 +19,6 @@ const { BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } = req
|
|||
const { TeamsBot } = require('./bots/teamsBot');
|
||||
const { MainDialog } = require('./dialogs/mainDialog');
|
||||
|
||||
// Read botFilePath and botFileSecret from .env file.
|
||||
const ENV_FILE = path.join(__dirname, '.env');
|
||||
require('dotenv').config({ path: ENV_FILE });
|
||||
|
||||
// Create adapter.
|
||||
// See https://aka.ms/about-bot-adapter to learn more about adapters.
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"url": "https://github.com/Microsoft/BotBuilder-Samples.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"botbuilder": "~4.9.1",
|
||||
"botbuilder-dialogs": "~4.9.1",
|
||||
"botbuilder": "~4.10.1",
|
||||
"botbuilder-dialogs": "~4.10.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"restify": "~8.5.1"
|
||||
},
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче