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);
}```
Related
Iam using SignalR to create my first chat App
every thing goes well but the problem is when I want to send message from one client to another not to all clients
the question is how can I target just one client by its connection id or user name ?
this is My server side code (Hub class)
i just want to know how to handel these methods in js to specify any client i want to send message to
public async Task SendMessageUser(string user, string message)
{
// here you need to set a specifc the user
await Clients.User("username").SendAsync("ReceiveMessage", user, message);
}
public async Task SendMessageToClient(string user, string receiverConnectionId, string message)
{
await Clients.Client(receiverConnectionId).SendAsync("ReceiveMessage", user, message);
}
public async Task SendMessageUsers(string user, string message)
{
// here you need to set the list of Users
await Clients.Users(new string[] { "myUser", "myUser2" }).SendAsync("ReceiveMessage", user, message);
}
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 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");
}
I have app for one person that has to display data on webpage from external device connected via usb port
Before, I gave user button "Start listening" that sent http request to backend which started listening on port (and blocked app, but it was fine because it is supposed to be used by exactly 1 person at time) until it received not-error response (SerialDataReceivedEvent/SerialErrorReceivedEvent)
and SerialData was returned from that request and displayed on page
I have to rewrite this using SignalR, so I quickly came with naive solution like this:
public class DeviceReaderHub : Hub
{
private readonly IConfiguration _config;
// this is static because listening that port (SerialPort) has to stay open
private static DeviceReader_Helper _service;
public DeviceReaderHub(IConfiguration config)
{
_config = config;
if (_service == null)
{
_service = new DeviceReader_Helper();
_service.Open(_config["DeviceInfo:Port"]);
}
_service.DataReceived_Delegate = SendMessage;
_service.ErrorReceived_Delegate = SendErrorMessage;
}
public async Task SendMessage(string message)
{
await Clients.All.SendAsync("onRead", message);
}
public async Task SendErrorMessage(string message)
{
await Clients.All.SendAsync("onRead", $"error = {message}");
}
public async override Task OnConnectedAsync()
{
await Clients.All.SendAsync("onConnected");
await base.OnConnectedAsync();
}
}
but I received reality-check very quickly - I cannot do it like that because DeviceReaderHub is disposed.
Exception thrown: 'System.ObjectDisposedException' in Microsoft.AspNetCore.SignalR.Core.dll
I thought about obtaining new DeviceReaderHub hub whenever SerialDataReceivedEvent or SerialErrorReceivedEvent is being Invoked
but I have not idea how can I get instance of the hub without losing connected clients
SignalR hubs are transient objects, which means that a new hub instance is used for each method call on the hub from the client. According to this Microsoft Docs:
Don't store state in a property on the hub class. Every hub method call is executed on a new hub instance.
So you should not use the hub to do anything other than receiving and handling requests from the client. To send messages to the client outside of the hub, SignalR provides the HubContext<T> class which is available from Dependency Injection. For example:
public class DeviceReader_Helper {
private readonly IHubContext<DeviceReaderHub> _hubContext;
// you can obtain hubContext either from constructor DI, or service locator pattern with an IServiceProvider
public DeviceReader_Helper(IHubContext<DeviceReaderHub> hubContext) {
_hubContext = hubContext;
}
public async Task SendMessage(string message) {
await _hubContext.Clients.All.SendAsync("onRead", message);
}
}
For more information see this. As for your concern that
but I have not idea how can I get instance of the hub without losing connected clients
Clients can be connected without a hub instance. Hubs are only used to receive messages from the client, and are not necessary to keep a client connected to the server.
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?