I'm trying to create a simple chat app using Azure Communication Services SDK for .NET.
I managed to add participants to a thread following
this example.
I read the documentation for class ChatParticipant and I found out that it can show the time from which the chat history is shared with the participant. The default date is 1/1/1970 00:00.
I would like to make this date variable, so that a user can only see messages from the moment he joined the chat on.
Is there a way to do it?
Thank you in advance
Can you try to set the property for ShareHistoryTime at the time of adding a participant to the Chat thread?. e.g in the below example, it is set to current time.
// ThreadId : Chat ThreadId , participantUserId : participant communication user Identifier
ChatThreadClient chatThreadClient =
chatClient.GetChatThreadClient(ThreadId);
chatThreadClient.AddParticipant(new ChatParticipant(
new CommunicationUserIdentifier(participantUserId))
{
DisplayName = displayName,
ShareHistoryTime = DateTimeOffset.Now
});
You can refer Chat Participant Properties here
Related
We have a bot design in Bot framework-4 using .Net c# sdk. This bot is hosted on IIS and available
on different channel such as Directline, MS Teams etc. We want to send proactive messages to all the user in MS teams to notify them irrespective of if they communicated with bot or not. The Proactive messages will be 1:1 message.
After doing lot of R&D we found that we will be only able to send Proactive message to user only when there conversation reference is present. (let me know if other way is also possible.)
Using below link and Sample to send Proactive message to user:
Proactive Message Sample
Document Referred
We are using cosmos DB container and auto save middleware for bot conversation state and user state management.
Code in ConfigureServices method of Startup.cs file:
var blobDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Blob service in your .bot file.");
var BlobDb = blobDbService as BlobStorageService;
var dataStore = new AzureBlobStorage(BlobDb.ConnectionString, BlobDb.Container);
var userState = new UserState(dataStore);
var conversationState = new ConversationState(dataStore);
services.AddSingleton(dataStore);
services.AddSingleton(userState);
services.AddSingleton(conversationState);
services.AddSingleton<ConcurrentDictionary<string, ConversationReference>>();
services.AddSingleton(new BotStateSet(userState, conversationState));
services.AddBot<EnterpriseTiBOT>(options =>
{
// Autosave State Middleware (saves bot state after each turn)
options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState));
}
Code to Store Conversation Reference for each user:
private void AddConversationReference(Activity activity)
{
var conversationReference = activity.GetConversationReference();
_conversationReferences.AddOrUpdate(conversationReference.User.Id, conversationReference, (key, newValue) => conversationReference);
}
protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
{
AddConversationReference(dc.Context, cancellationToken);
}
Code in notifyContoller is same as the code from GitHub Sample. There are 2 issues we are facing :
The concurrent dictionary having conversation reference become blank when the IIS pool is recycled and we are not able to send the proactive message to the user, how to store it in Blob storage and access the same in Notify controller?
We want to send proactive message to all the user whether they have communicated with bot or not, any way to achieve this? Tried 3rd approach from this article. But the challenge is, we are not able to send message to user based on User ID or user principle name.
There are multiple ways to store the conversation and user info. You should store these details in more persistent place rather than in memory. Here is a sample app code which stores user detail and along with the conversation Id in cosmos DB at the time of installation of the app. You could look into the implementation part. It can be any storage (blob, SQL).
For sending proactive message, User must have access to your app. You could make your app install for everyone in the tenant from Teams admin portal. Here is a reference documentation for managing the app from admin portal.
You need to have the conversation ID (between a bot and user) for sending a proactive message. And the conversation Id is created when the bot is installed for an user Or in team/group where user is part of.
I want to add comment to the answer but I do not have enough reputation to do so. Just to eleborate point 1 , if you want to ask where can we get and save the conversation refences, you can get it via method named: OnConversationUpdateActivityAsync.
It took me some time to get to this, so I think it is useful to share.
You can get a lot of information eg user ID, channel ID from the activity, here is some sample code:
public class ProactiveBot : ActivityHandler
{
...
...
protected override Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var conversationReferences = turnContext.Activity.GetConversationReference();
//this is your user's ID
string userId = conversationReference.User.Id;
//this is the bot's ID and will be the same for all activities under same bot.
string botId = conversationReference.Bot.Id;
...
...
...
}
}
I have an application where two calls are connected to a conference via Twilio. In the current implementation what happens is, when the first call is answered, a message using <Say> attribute is played and then is dialled into a conference. While the other person connects, there is an mp3 added as the waitUrl. The code for this is shown below.
var dial = new Dial()
.Conference(sessionId.ToString(),
startConferenceOnEnter: true,
waitUrl: new Uri(this.musicUrl),
waitMethod: Twilio.Http.HttpMethod.Get,
statusCallbackEvent: callbackEvents,
statusCallback: new Uri("url")
);
response.Say(message).Append(dial);
My question is, Is it possible to play a message, then the mp3 within the waitUrl instead of adding <Say> before dialling.
I don't see the waitUrl as an attribute that can be updated in a conference, as shown in the documentation here.
Conference Resource (Update a Conference Resource)
You can look at the Conference Participants API / Agent Conference Create a Participant option and earlyMedia set to true and then update the announceUrl to play updates to a participant or all participants. It is not clear from your question what information you are trying to convey to the participant(s).
Is it possible to change the name of the bot during runtime. Current the name which i have added in portal is getting displayed under bot message. Is it possible to update it in run time rather than displaying the name configured in portal.
You can intercept all messages that are exchanged between user and bot, and you can check the value of activity.From.Name to detect if the message sent from your bot, and then you can specify a new value for activity.From.Name property, which would help achieve your requirement to show updated display name in webchat.
public async Task LogAsync(IActivity activity)
{
if (activity.From.Name== "fehanbasicbot")
{
activity.From.Name = "testbot";
}
}
Test result:
My bot settings:
In webchat:
I'm trying to write something in C#, a simple console app that will connect to Discord, retrieve a list of all users in a channel (all currently online would suffice, but everyone who has channel access would be even better.) The app does not need to maintain a connection, just jump in, grab the list of user names and jump out.
I've experimented with DiscordSharp, but it doesn't seem to quite be working out. I think I am getting a client connection but I can't seem to find any channels via GetChannelByName or GetChannelByID. I am not set on using DiscordSharp as the only solution, though I do like the library so far.
A "server" in discord is called a Guild. Per the documentation a Guild can have a list of Channel objects. In the Channel object there is a property called recipients which should give you all users of that channel.
I wouldn't recommend using DiscordSharp because according to their GitHub it is a dead project. They recommend using DSharpPlus or Discord.NET.
I just checked the documentation for Discord.NET and found a few methods you could use:
GetGuildAsync(UInt64, RequestOptions): This will get you the RestGuild (server) based on the server ID.
GetChannelAsync(UInt64, RequestOptions): This will get you the RestChannel based on the channel ID.
Using either one of these will eventually get you a RestChannel object that will contain a GetUsersAsync(CacheMode, RequestOptions) method that will allow you to get the collection of IUSer
In a command module you can do this:
public class AllUsers : ModuleBase<SocketCommandContext>
{
public async Task Traitement()
{
var users = Context.Guild.Users;
//you can loop here on users and do the traitement
}
}
I have always been using Parse to manage my backend but switched to Azure due to the better integration with ASP.NET and Xamarin. In Parse I created a PFInstallation object and associated whatever property I needed to filter on before sending push notifications.
In Azure Mobile Services I am using the following code (in Xamarin iOS) to register the device:
public override void RegisteredForRemoteNotifications (UIApplication application, NSData deviceToken)
{
try {
var languageCode = NSLocale.PreferredLanguages [0];
ServiceClient.GetPush ().RegisterNativeAsync (deviceToken, new []{ languageCode }).ContinueWith ((t) => {
Console.WriteLine ("Device registration successful!");
});
} catch (Exception e) {
Console.WriteLine ("Could not register device for push notifications: {0}", e.Message);
}
}
I would like to have a way to remind my inactive users that they should play again. In Parse I just associated a "lastLoginDate" attribute to the PFInstallation object. How can I achieve the same with Azure Mobile Services?
As of now I am only able to filter based on the user's device language (because I save it as a tag) but not on the "lastLoginDate".
PS: in my backend I would like to have a code like this
var users = registrations.Where(u => u.LastLoginDate <= testDate);
SendNotificationToUsers(users);
UPDATE
I read on this page that you can use Tag Expressions to filter registrations but in the article it's not specified if you can use boolean expressions involving a date comparison. Any help on this?
Thank you.
One approach would be to have the device register with a tag with the current date each time the user opens the app. So today I use the app, I register my token for the tag "last-use-2015-03-02". Tomorrow if I use the app again I will reregister with the tag "last-use-2015-03-03", replacing the device registration for 2015-03-02.
Then each day have a scheduler that sends a message to the tag for a week ago (for example). So a week from now on March 9, I can send a notification to all devices with the tag "last-use-2015-03-02" reminding them to come back.