com.microsoft.bot.builder.classic.dialogs.BotToUser Maven / Gradle / Ivy
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Bot Framework: http://botframework.com
//
// Bot Builder SDK GitHub:
// https://github.com/Microsoft/BotBuilder
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
package com.microsoft.bot.builder.classic.dialogs;
import com.microsoft.bot.schema.models.MessageActivity;
import java.util.concurrent.CompletableFuture;
///
/// Methods to send a message from the bot to the user.
///
public interface BotToUser
{
///
/// Post a message to be sent to the user.
///
/// The message for the user.
/// The cancellation token.
/// A task that represents the post operation.
// TODO: daveta Cancellation Token
//CompletableFuture PostAsync(IMessageActivity message, CancellationToken cancellationToken = default(CancellationToken));
CompletableFuture PostAsync(MessageActivity message);
///
/// Make a message.
///
/// The new message.
MessageActivity MakeMessage();
}
/*
public final class NullBotToUser implements BotToUser
{
private final MessageActivity toBot;
public NullBotToUser(MessageActivity toBot)
{
SetField.NotNull(out this.toBot, nameof(toBot), toBot);
}
MessageActivity BotToUser.MakeMessage()
{
var toBotActivity = (Activity)this.toBot;
return toBotActivity.CreateReply();
}
Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
public sealed class PassBotToUser : IBotToUser
{
private readonly IBotToUser inner;
public PassBotToUser(IBotToUser inner)
{
SetField.NotNull(out this.inner, nameof(inner), inner);
}
IMessageActivity IBotToUser.MakeMessage()
{
return this.inner.MakeMessage();
}
async Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
await this.inner.PostAsync(message, cancellationToken);
}
}
public sealed class AlwaysSendDirect_BotToUser : IBotToUser
{
private readonly IMessageActivity toBot;
private readonly IConnectorClient client;
public AlwaysSendDirect_BotToUser(IMessageActivity toBot, IConnectorClient client)
{
SetField.NotNull(out this.toBot, nameof(toBot), toBot);
SetField.NotNull(out this.client, nameof(client), client);
}
IMessageActivity IBotToUser.MakeMessage()
{
var toBotActivity = (Activity)this.toBot;
return toBotActivity.CreateReply();
}
async Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
await this.client.Conversations.ReplyToActivityAsync((Activity)message, cancellationToken);
}
}
public sealed class V4Bridge_BotToUser : IBotToUser
{
private readonly Microsoft.Bot.Builder.ITurnContext context;
public V4Bridge_BotToUser(Microsoft.Bot.Builder.ITurnContext context)
{
SetField.NotNull(out this.context, nameof(context), context);
}
IMessageActivity IBotToUser.MakeMessage()
{
var toBotActivity = (Activity)this.context.Activity;
return toBotActivity.CreateReply();
}
Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
// TODO, change this to context.SendActivity with M2 delta
return this.context.Adapter.SendActivities(this.context, new Activity[] { (Activity) message });
}
}
public interface IMessageQueue
{
Task QueueMessageAsync(IBotToUser botToUser, IMessageActivity message, CancellationToken token);
Task DrainQueueAsync(IBotToUser botToUser, CancellationToken token);
}
public sealed class AutoInputHint_BotToUser : IBotToUser
{
private readonly IBotToUser inner;
private readonly IMessageQueue queue;
public AutoInputHint_BotToUser(IBotToUser inner, IMessageQueue queue)
{
SetField.NotNull(out this.queue, nameof(queue), queue);
SetField.NotNull(out this.inner, nameof(inner), inner);
}
async Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
await this.queue.QueueMessageAsync(inner, message, cancellationToken);
}
IMessageActivity IBotToUser.MakeMessage()
{
return inner.MakeMessage();
}
}
public sealed class InputHintQueue : IMessageQueue
{
private readonly Queue queue = new Queue();
private readonly IChannelCapability channelCapability;
private readonly Func makeStack;
public InputHintQueue(IChannelCapability channelCapability, Func makeStack)
{
SetField.NotNull(out this.channelCapability, nameof(channelCapability), channelCapability);
SetField.NotNull(out this.makeStack, nameof(makeStack), makeStack);
}
async Task IMessageQueue.QueueMessageAsync(IBotToUser botToUser, IMessageActivity message, CancellationToken token)
{
// This assumes that if InputHint is set on message, it is the right value that channel expects
// and will NOT queue the message
if (this.channelCapability.ShouldSetInputHint(message))
{
// drain the queue
while (this.queue.Count > 0)
{
var toUser = this.queue.Dequeue();
toUser.InputHint = InputHints.IgnoringInput;
await botToUser.PostAsync(toUser, token);
}
queue.Enqueue(message);
}
else
{
await botToUser.PostAsync(message, token);
}
}
async Task IMessageQueue.DrainQueueAsync(IBotToUser botToUser, CancellationToken token)
{
while (this.queue.Count > 0)
{
var toUser = this.queue.Dequeue();
// last message in the queue will be treated specially for channels that need input hints
if (this.queue.Count == 0)
{
var stack = this.makeStack();
if (this.channelCapability.ShouldSetInputHint(toUser) && stack.Frames.Count > 0)
{
var topOfStack = stack.Frames[0].Target;
// if there is a prompt dialog on top of stack, the InputHint will be set to Expecting
if (topOfStack != null && topOfStack.GetType().DeclaringType == typeof(PromptDialog))
{
toUser.InputHint = InputHints.ExpectingInput;
}
else
{
toUser.InputHint = InputHints.AcceptingInput;
}
}
}
else
{
if (this.channelCapability.ShouldSetInputHint(toUser))
{
toUser.InputHint = InputHints.IgnoringInput;
}
}
await botToUser.PostAsync(toUser, token);
}
}
}
public interface IMessageActivityMapper
{
IMessageActivity Map(IMessageActivity message);
}
#pragma warning disable CS0618
public sealed class KeyboardCardMapper : IMessageActivityMapper
{
public IMessageActivity Map(IMessageActivity message)
{
if (message.Attachments.Any())
{
var keyboards = message.Attachments.Where(t => t.ContentType == KeyboardCard.ContentType).ToList();
if (keyboards.Count > 1)
{
throw new ArgumentException("Each message can only have one keyboard card!");
}
var keyboard = keyboards.FirstOrDefault();
if (keyboard != null)
{
message.Attachments.Remove(keyboard);
var keyboardCard = (KeyboardCard)keyboard.Content;
if (message.ChannelId == "facebook" && keyboardCard.Buttons.Count <= 10)
{
message.ChannelData = keyboardCard.ToFacebookMessage();
}
else
{
message.Attachments.Add(keyboardCard.ToHeroCard().ToAttachment());
}
}
}
return message;
}
}
#pragma warning restore CS0618
public sealed class SetLocalTimestampMapper : IMessageActivityMapper
{
public IMessageActivity Map(IMessageActivity message)
{
if (message.LocalTimestamp == null)
{
message.LocalTimestamp = DateTimeOffset.UtcNow;
}
return message;
}
}
public sealed class MapToChannelData_BotToUser : IBotToUser
{
private readonly IBotToUser inner;
private readonly IEnumerable mappers;
public MapToChannelData_BotToUser(IBotToUser inner, IEnumerable mappers)
{
SetField.NotNull(out this.inner, nameof(inner), inner);
SetField.NotNull(out this.mappers, nameof(mappers), mappers);
}
public async Task PostAsync(IMessageActivity message, CancellationToken cancellationToken = new CancellationToken())
{
foreach (var mapper in mappers)
{
message = mapper.Map(message);
}
await this.inner.PostAsync(message, cancellationToken);
}
public IMessageActivity MakeMessage()
{
return this.inner.MakeMessage();
}
}
public sealed class BotToUserTextWriter : IBotToUser
{
private readonly IBotToUser inner;
private readonly TextWriter writer;
public BotToUserTextWriter(IBotToUser inner, TextWriter writer)
{
SetField.NotNull(out this.inner, nameof(inner), inner);
SetField.NotNull(out this.writer, nameof(writer), writer);
}
IMessageActivity IBotToUser.MakeMessage()
{
return this.inner.MakeMessage();
}
async Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
await this.inner.PostAsync(message, cancellationToken);
await this.writer.WriteLineAsync($"{message.Text}{ButtonsToText(message.Attachments)}");
}
private static string ButtonsToText(IList attachments)
{
var cardAttachments = attachments?.Where(attachment => attachment.ContentType.StartsWith("application/vnd.microsoft.card"));
var builder = new StringBuilder();
if (cardAttachments != null && cardAttachments.Any())
{
builder.AppendLine();
foreach (var attachment in cardAttachments)
{
string type = attachment.ContentType.Split('.').Last();
if (type == "hero" || type == "thumbnail")
{
var card = (HeroCard)attachment.Content;
if (!string.IsNullOrEmpty(card.Title))
{
builder.AppendLine(card.Title);
}
if (!string.IsNullOrEmpty(card.Subtitle))
{
builder.AppendLine(card.Subtitle);
}
if (!string.IsNullOrEmpty(card.Text))
{
builder.AppendLine(card.Text);
}
if (card.Buttons != null)
{
foreach (var button in card.Buttons)
{
builder.AppendLine($"* {button.Title}");
}
}
}
}
}
return builder.ToString();
}
}
*/
© 2015 - 2025 Weber Informatics LLC | Privacy Policy