I have a bot that does a hand-off to a human operator.
When the operator joins I receive an event in the 'OnEventActivityAsync' event.
At that moment I want to send a message to the client that they're connected to the operator.
How do I change the turnContext/Activity to send the message to the client?
Not entirely sure which part of code to post. (can't post entire project due to company policies)
protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
if (turnContext.Activity.Name == "webchat/agentJoin")
{
_logger.LogInformation("webchat/agentJoin");
//Database stuff here
await turnContext.SendActivityAsync(MessageFactory.Text("Connected to customer"), cancellationToken);
//How do I send a message to the client here? turnContext sends the message to the agent, not client
}
}
Please See protocol definition in the below GitHub link experimentations:
https://github.com/microsoft/BotBuilder-Samples/tree/master/experimental/handoff-library
Factory Methods
SDK will include the following factory method to aid in creation of the events specified:
C#:
namespace Microsoft.Bot.Builder
{
public static class EventFactory
{
public static IEventActivity CreateHandoffInitiation(
ITurnContext turnContext,
object handoffContext,
Transcript transcript);
public static IEventActivity CreateHandoffResponse(
ConversationAccount Conversation,
string code);
public static IEventActivity CreateHandoffCompleted(
ConversationAccount Conversation,
string code,
Transcript transcript);
}
}
Protocol codes are defined as follows:
namespace Microsoft.Bot.Schema
{
public static class HandoffCodes
{
public const string Accepted = "accepted";
public const string Failed = "failed";
public const string TimedOut = "timedOut";
public const string EndOfConversation = "endOfConversation";
public const string TransferBack = "transferBack";
}
}
Thanks to the suggestion by Mick I took another look at proactive messages.
I had looked at it before, but never got it to work because of 'Unauthorized' errors.
Now I noticed there's a fix for that specific problem.
The code is based on the MS documentation for sending proactive notifications:
Send proactive Notifications
So what I do is:
turnContext.Adapter.ContinueConversationAsync(_appId, conversationReference, BotCallback, default(CancellationToken));
private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
{
// If you encounter permission-related errors when sending this message, see
// https://aka.ms/BotTrustServiceUrl
await turnContext.SendActivityAsync("You're now connected to: Ted");
}
Related
I'm having difficulty setting up an end-point to receive Google Play Developer Notifications via Pub/Sub in a c# controller. I've set everything up against the app to publish to a topic and I have successfully setup a subscription in Google Pub/Sub...and the test notification is coming through on Google Pub/Sub...the problem is I am having trouble receiving the push notification on my server side c# controller end-point...I'm not sure how to set that up and if I have the correct json signature. I can't find any examples or documentation around this. Any help would be appreciated!
This is my first "test" of Pub/Sub and this sample worked for me.
See all samples here: https://github.com/GoogleCloudPlatform/dotnet-docs-samples/tree/main/pubsub/api/Pubsub.Samples
These steps needs to be done:
Create a topic here: https://console.cloud.google.com/cloudpubsub/topic/ , in the example we call it "iap"
Under permission for "iap", add google-play-developer-notifications#system.gserviceaccount.com as Pub/Sub publisher. This will allow Google Play to publish on this topic.
Under subscriptions https://console.cloud.google.com/cloudpubsub/subscription add your service account/personal gmail or what ever that is linked to your c# server later on. I tested firebase-adminsdk#yourproject.iam.gserviceaccount.com and it worked fine. Check your environment variable "GOOGLE_APPLICATION_CREDENTIALS" and extract this user as Pub/Sub subscriber in permissions for "iap-sub".
Play store needs to be configured under "Monetization setup". String are for instance: projects/yourproject/topics/iap
Press a test message (you can also see it in the Cloud console)
Test message could look something like this:
20:16:07: Received message 6108129433484522 20:16:07:
{"version":"1.0","packageName":"com.yourproject","eventTimeMillis":"1666642564858","testNotification":{"version":"1.0"}}
Class below runs the client in the background without waiting.
If you just wanna try in a console, use the Console.ReadLine()
public class GCloudPubSub : IDisposable
{
public String projectId { get; set; }
public String subscriptionId { get; set; }
private SubscriberClient _client;
public FirebasePubSub() {
projectId = "yourproject";
subscriptionId = "iap-sub";
}
public async void Start()
{
SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);
_client = await SubscriberClient.CreateAsync(subscriptionName);
await _client.StartAsync(HandleMessage);
}
public async void Stop()
{
await _client.StopAsync(CancellationToken.None);
}
public void Dispose()
{
Stop();
}
static Task<SubscriberClient.Reply> HandleMessage(PubsubMessage message, CancellationToken token)
{
Log($"Received message {message.MessageId}");
string text = System.Text.Encoding.UTF8.GetString(message.Data.ToArray());
Log(text);
return Task.FromResult(SubscriberClient.Reply.Ack);
}
static void Log(string text) => Console.WriteLine($"{DateTime.UtcNow:HH:mm:ss}: {text}");
}
Hopefully this will lead you on the right way :)
I'd like to send a signal from my C# API code, probably using the SendSignal activity to a workflow that will receive that signal using the SignalReceived activity.
To send a signal to a workflow from your own code, such as a controller or any other class, you can use the ISignaler service.
Here's an example:
[ApiController]
[Route("myapi")]
public class MyApi: Controller
{
private readonly ISignaler _signaler;
public MyApiController(ISignaler signaler)
{
_signaler = signaler;
}
[HttpPost("send-signal")]
public async Task<IActionResult> SendSignal(CancellationToken cancellationToken)
{
var startedWorkflows = await _signaler.TriggerSignalAsync("MySignal", cancellationToken: cancellationToken);
return Ok(startedWorkflows);
}
}
A complete sample project can be found here.
I am trying to make a bot command to create a private channel, however, when I call it nothing happens even though the bot has full Administrator permissions granted.
Here is the command:
```[Command("makeprivate")]
public async Task MakePrivate(CommandContext ctx, string name)
{
await ctx.Guild.CreateChannelAsync( name, ChannelType.Private ).ConfigureAwait(false);
}```
I'm using .net 5 azure function with ServiceBusTrigger. In previous versin. I was using a parametr MessageReceiver to tell azure that I compleated task. For that I used
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
My problem is that i new version (.net5) unlike the previous version (.net core 3.1) is param in string (json) not in object (maybe it's the error but I don't know which object to use, object I tried was Microsoft.Azure.ServiceBus.Core.MessageReceiver).
But now i do not have the object so i can not call the method.
Does someone knows the answer? Thak you for your time.
Example of my code:
Function("TasksFunction")]
public async Task Run([ServiceBusTrigger("queue", Connection = "ConnectionString")] string message, string id, MessageReceiver messageReceiver, FunctionContext executionContext)
{
try
{
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
await DoWorkAsync(messageReceiver, message);
}
catch (Exception e)
{
log.LogCritical(e);
}
}
Try to bind your message to Message type instead of string
public async Task Run([ServiceBusTrigger("queue", Connection = "ConnectionString")] Message message, string id, MessageReceiver messageReceiver, FunctionContext executionContext)
Message has property SystemPropertiesCollection and use message.SystemProperties.LockToken
I am trying to implement Azure SignalR Service to facilitate two way messaging between a desktop, asp.net-core and a xamarin.ios apps.
I have created a Hub as per Microsoft's documentation here:
https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-2.2
Hub:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
I add users's connections to a group when they connect to the hub as shown here: https://learn.microsoft.com/en-us/aspnet/core/signalr/groups?view=aspnetcore-2.2
Add to Group:
public async Task AddToGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {groupName}.");
}
public async Task RemoveFromGroup(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has left the group {groupName}.");
}
When a message is sent it has a group name as a parameter, I would like to check if the provided group has any connections before sending the message to any registered clients, if there are no connections, I would like to send a push notification (already have working code for the push notification)
Send Message with Notification Fallback:
public class ChatHub : Hub
{
public Task SendMessage(string groupName, string user, string message)
{
var group = Clients.Group(groupName);
// todo: how to check if we have any open connections in this group?
if(group.Conections.Count > 0)
{
return group.SendAsync("ReceiveMessage", user, message);
}
else
{
// todo: run code to send push notification or anything else you might want to do
}
}
}
Problem: I don't see any way to check for the number of connections currently in a group via the available api (correct me if I'm wrong)
I see the group coming back as Microsoft.AspNetCore.SignalR.Internal.GroupProxy<ChatHub> at runtime with no public methods. Internal private variables do include _groupName and _lifeTimeManager and within lifetime manager there is a _clientConnectionManager which i can see has client connections when they are connected but I have no access to any of these, I'm using the Microsoft.Azure.SignalR (1.0.4) Nuget package. Does anyone know if what I'm trying to do possible with this SDK and if so how I can do this?