pass httpheader to the conversationupdated event - directline - c#

Sending custom http header value while starting a conversation with the bot using DirectLine client. Was expecting it in the ConversationUpdate event in which I'm not able to finding it in the Request.Headers["userName"]
headers.Add("userName", name);
var conversation = await directLine.Conversations.StartConversationWithHttpMessagesAsync(headers);

The customHeaders parameter is automatically included in the client when generated by autorest, but it is not being used.
Initiating a direct line conversation with a specified from.Name is currently a prioritized backlog item.
I'm sorry these are not the answers you're looking for.

Related

DSharpPlus send an embed to a specific channel?

I'm new to working with discord bots and I was wondering if anybody knew a way to send embedded messages to specific channels. The only way I've found so far to send one is to use RespondAsync which just directly replies to whoever issues the command in the same channel. The purpose of my bot is to create automated link directories in read only channels and the command will just refresh them. Having trouble finding much Dsharpplus c# examples, and I'm terrible at making sense of documentation. Any help would be appreciated.
await ctx.RespondAsync(embed);
this is what I've been using to send my embeds for testing purposes, but like I said I'd like to send it in a way that it posts to a specified channel
You just need to get the DiscordChannel object of the channel(s) you want to send the embed. You can get the ID of the channel via right-click in Discord and "Copy ID"
DiscordChannel channel = await _client.GetChannelAsync(ID_OF_CHANNEL);
DiscordEmbedBuilder embed = new DiscordEmbedBuilder
{
Color = DiscordColor.SpringGreen,
Description = "Good to see you!",
Title = "Hello World"
};
await channel.SendMessageAsync(embed: embed);
The DiscordGuild class also has GetChannelAsync you can use.

Azure service bus delete queue message by id using the .net sdk

I have an Azure Service Bus Queue filled with messages and I want to delete a message based on it's ID.
The REST API provides this solution by http request:
DELETE http{s}://{serviceNamespace}.servicebus.windows.net/{queuePath}/messages/{messageId}/{lockToken}
For the .net 5 sdk, Microsoft provides a solution without using the message's id but rather a receivedMessage object
string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);
// create a receiver that we can use to receive and settle the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
// complete the message, thereby deleting it from the service
await receiver.CompleteMessageAsync(receivedMessage);
I want to delete a message by it's id, using the .net sdk.
There's no way to achieve it with a simple command, unfortunately. Some of this was discussed here. You could add your voice to the thread and, hopefully, it will reach the right audience.

Telegram Bot API C# How to get All Pinned Messages?

Telegram added the feature to pin more than one message. I'm doing it like this:
var chat = botClient.GetChatAsync(chatid).Result;
pinnedmsgtxt = chat.PinnedMessage.Text;
pinnedmsg= chat.PinnedMessage;
but I can only get the last message that was pinned. Any way to get all of them? Am I missing something? I'm using https://github.com/TelegramBots/telegram.bot
Use messages.search method with inputMessagesFilterPinned filter.
Please read more here:
Pin API
Message Search API
Pinned messages filter

Resume Bot Framework dialog when triggered by external service

The Scenario
I have a bot built using the Bot Framework with a series of dialogs. One of these dialogs gives the user the option of inputting some complex data via a web page by presenting a button to them. Clicking the button they are then taken to the site, fill out the data, save and are then directed back to the bot.
I want my bot to pause the dialog until it receives an event from my web page telling me the user has saved the data and then continue asking the user questions.
Before
I had a version implemented whereby I would store a ConversationReference before the user clicked the button and then when the external event happened I would send the cards and next messages I wanted to show (not in a dialog) from a webhook, that was fine but it got quite complicated/messy - I'd rather keep the whole app in one continuous dialog.
Idea 1: Use DirectLine API
I did some research and many people were suggesting using the DirectLine API. So I implemented this:
public async Task SendEventAsync(InternalEventMessage message, ConversationReference reference) {
var client = new DirectLineClient(!String.IsNullOrEmpty(_settings.DirectLineSecret) ? _settings.DirectLineSecret : null);
if (_settings.SiteUrl.Contains("localhost")) {
client.BaseUri = new Uri(_settings.DirectLineServiceUrl);
}
var eventMessage = Activity.CreateEventActivity();
//Wrong way round?!?
eventMessage.From = reference.Bot;
eventMessage.Type = ActivityTypes.Event;
eventMessage.Value = message;
var conversation = await client.Conversations.PostActivityAsync(reference.Conversation.Id, eventMessage as Activity);
}
This uses the DirectLine client to send an event message to the serviceUrl using a stored ConversationReference, basically imitating a user (bot and user seem to be the wrong way round in the SDK). Checking for localhost was so that the DirectLine library pointed at the emulator server rather than https://directline.botframework.com.
In my dialog I call:
//method above shows input button and links to web page
context.Wait(WaitForAddressInput);
}
private async Task WaitForAddressInput(IDialogContext context, IAwaitable<IActivity> result) {
var message = await result;
switch (message.Type) {
case ActivityTypes.Message:
//TODO: Add response
break;
case ActivityTypes.Event:
var eventMessage = message as IEventActivity;
if (((JObject)eventMessage.Value).ToObject<InternalEventMessage>().Type == EventType.AddressInputComplete) {
_addressResult = (await _tableService.ReadOrderById(Order.OrderId)).Address;
await context.PostAsync($"Great}");
context.Done(_addressResult);
}
break;
}
}
This waits for any message from the user after the button has been shown and if our event matches then we proceed with the dialog.
This works locally using the emulator but, frustratingly, doesn't live. It fails to recognise channels created via webchat or Messenger. That is explained here: Microsoft Bot Framework DirectLine Can't Access Conversations
For security reasons, you can't use DirectLine to spy on messages from
another conversation.
So I can't access a channel that I haven't created using DirectLine.
Idea 2: BotConnector
So I thought I'd try the BotConnector using similar code:
public async Task SendEventAsync(InternalEventMessage message, Microsoft.Bot.Connector.DirectLine.ConversationReference reference) {
var botAccount = new ChannelAccount(reference.User.Id, reference.User.Name);
var userAccount = new ChannelAccount(reference.Bot.Id, reference.Bot.Name);
MicrosoftAppCredentials.TrustServiceUrl(reference.ServiceUrl);
var connector = new ConnectorClient(new Uri(reference.ServiceUrl), new MicrosoftAppCredentials("xxxxxxxxxxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxx"));
connector.Credentials.InitializeServiceClient();
var eventMessage = Activity.CreateMessageActivity();
eventMessage.Recipient = botAccount;
eventMessage.From = userAccount;
eventMessage.Type = ActivityTypes.Event;
eventMessage.Conversation = new ConversationAccount(id: reference.Conversation.Id);
eventMessage.ServiceUrl = reference.ServiceUrl;
eventMessage.Timestamp = DateTimeOffset.UtcNow;
eventMessage.LocalTimestamp = DateTime.Now;
eventMessage.ChannelId = reference.ChannelId;
var result = await connector.Conversations.SendToConversationAsync(eventMessage as Microsoft.Bot.Connector.Activity);
}
This doesn't crash and I can see the event appear in the emulator request console but nothing happens, it seems to be ignored!
Idea 3: Try to imitate the bot service calling my bot
I haven't tried this yet because I think it might be the most time consuming but I was reading here about the service authentication and wondered if it would be possible to imitate the hosted bot service sending a message and send my event that way with the required data?
This seems like a fairly common scenario so I'm surprised I haven't come across a way to do this yet. If anyone has any other ideas on how I can send an event message to my bot from an external service then I'd love to hear it.
Update:
See my answer below Eric's to see what I did.
Idea 1:
DirectLine is a channel, not a library to use in order to connect to channels. (For instance: you would not use Facebook Messenger to connect to Skype) DirectLineClient is useful for creating a client application that connects to the DirectLine channel through the Direct Line connector service.
Idea 2:
This method should work. In fact, the BotAuth library uses this method for the MagicNumber login flow within the CallbackController: https://github.com/MicrosoftDX/botauth/blob/9a0a9f1b665f4aa95b6d60d09346dda90d8b314e/CSharp/BotAuth/Controllers/CallbackController.cs
For your scenario, you should be able to construct a CardAction of type ActionTypes.OpenUrl that contains a value with the ConversationReference encoded in the url. Clicking the button will call an mvc controller that displays a page (saving the ConversationReference in a cookie or something) and when the user finishes adding the address on the page, use the ConversationReference to send an event to the bot (similar to how BotAuth resumes the conversation in the CallbackController).
Idea 3:
This would bypass the connector services, and is not a supported scenario. The link you shared explains the details of how authentication works in the Bot Framework, not how to bypass the connector services.
Eric's answer led me to solve the issue using the BotAuth example but, for completeness, here is what I did using Idea 2.
I created a CallbackController on my Bot Framework endpoint and then used the following code to send an event back to the awaiting dialog:
MicrosoftAppCredentials.TrustServiceUrl(reference.ServiceUrl);
var message = reference.GetPostToBotMessage();
message.Value = new InternalEventMessage(type);
message.Type = ActivityTypes.Event;
await Conversation.ResumeAsync(reference, message);
The dialog awaits with this code and continues:
context.Wait(WaitForAddressInput);
}
private async Task WaitForAddressInput(IDialogContext context,
IAwaitable<IActivity> result)
{
var message = await result;
switch (message.Type)
{
case ActivityTypes.Message:
//TODO: Add response
break;
case ActivityTypes.Event:
//Process event and continue!
break;
}
}
This is the most complicated issue I've had with the Bot Framework and I found the docs a little lacking. Hope this helps someone!

How to Update Account in StripeApi using C#?

I am trying to update Account in Stripe Api using Stripe.netlibrary ,using StripeAccountService and storing it in StripeAccountclass which i made by myself to store the result returned by API :
var accountService = new StripeAccountService("secretKey in string");
StripeRequestOptions option = new StripeRequestOptions();
option.StripeConnectAccountId = "AccountId to update";
StripeAccount x = accountService.Get(option);
x.Email = "Local#local.com";
//Then i do not know how to save changes back to api now.
But StripeAccountService class has no Update method define. How I can perform update on the Account.
I am using this library. Stripe api does have an update method too here.
Stripe.net does not support managed accounts: "Managed Accounts are a valuable service as well, but they are not available in Stripe.net yet." https://github.com/jaymedavis/stripe.net#stripe-connect
Stripe.net doesnot support Managed account but it can be done using following approach it is for update account.
I won't be able to give code but can provide the correct approach, it is tested.
https://api.stripe.com/v1/account
is the Url for updating stripe account.
Now you need to add two header and a body you can try WebRequest or httpclient class.
The reason i am unable to provide code because i did not do any research in adding multiple headers and a body.
so it would look something like this
Header
Property value
Authorization bearer "SecretKey"
Stripe-Account "acct_16uR8kKN01245679"
Body
Property value
email "test#test.com"
support_phone "555-867-5309"
You can see complete property list here. i picked few for demonstration purpose only.
Then save the response in any variable and it is done.

Categories