使用网络应用程序通过机器人主动发送消息 [英] Proactively sending message through bot using a web app
问题描述
感谢用户MarkMoose,我意识到我的数据库表没有存储完整的ID. 未来的调试器:如果这不能帮助您解决问题,请查看我与MarkMoose的对话,他们会引导我完成非常有用的故障排除步骤.
Thanks to user MarkMoose I realized that my database table was not storing the full IDs. Future debuggers: If that does not help you solve your problem please look at my conversation with MarkMoose, they walked me through very useful troubleshooting steps.
我正在尝试使用Microsoft Bot SDK版本4.0创建一个在Azure上托管的Microsoft Teams机器人.
I am trying to create a Microsoft Teams bot hosted on Azure using Microsoft Bot SDK Version 4.0.
流程如下
-
Web应用程序警报触发器.向包含以下内容的bot发送POST请求(从用户先前的消息中收集的所有这些数据)
Web app alarm triggers. Sends a POST request to the bot that contains (all this data gathered from a previous message from the user)
- 收件人ID(收件人用户的身份)
- 收件人(收件人用户)
- 来自ID(我的机器人)
- 来自名字(我的机器人)
- 频道ID
- 对话ID
- (收件人用户的)服务URL
Bot从JSON提取信息形成新的消息活动
Bot extracts that info from JSON forms new message activity
问题::当漫游器尝试使用上面列出的凭据创建ConversationAccount
对象时,它将引发以下错误:
Problem: When the bot attempts to create a ConversationAccount
object using the credentials listed above it throws the following error:
捕获到异常:Microsoft.Bot.Schema.ErrorResponseException:操作返回了无效的状态码'BadRequest'
Exception caught: Microsoft.Bot.Schema.ErrorResponseException: Operation returned an invalid status code 'BadRequest'
这是代码相关部分的一部分.
Here is the part of the relevant part of the code.
请特别注意以下几行:
var account = new MicrosoftAppCredentials(botCreds["App ID"], botCreds["App Password"]);
var jwtToken = await account.GetTokenAsync();
ConnectorClient connector = new ConnectorClient(new System.Uri(serviceURL), account);
当我找到其他人对我的问题的解决方案时,这些区别略有不同.在当前的代码版本中,我正在使用此解决方案.我还尝试了他创建的DelegatingHandler类,但它引发了相同的错误.
These are the lines that slightly differ when I found other peoples solutions to my problem. In my current version of the code I am using this posts solution. I have also tried the DelegatingHandler class he created but it throws the same error.
/// <summary>
/// Sends a message to a user or group chat.
/// </summary>
/// <param name="forwardContext">JSON object containing credentials for destination chat.</param>
/// <param name="messageToSend">The message to forward.</param>
/// <returns></returns>
private async Task ForwardMessage(JToken forwardContext, string messageToSend)
{
// Collect data from JSON input
var restCmd = forwardContext;
var toId = (string) restCmd["toId"];
var toName = (string) restCmd["toName"];
var fromId = (string) restCmd["fromId"];
var fromName = (string) restCmd["fromName"];
var channelId = (string) restCmd["channel"];
var serviceURL = (string) restCmd["serviceURL"];
var conversationId = (string) restCmd["conversation"];
var cred_str = $@"toId: {toId}
toName: {toName}
fromId: {fromId}
fromName: {fromName}
channelId: {channelId}
serviceURL: {serviceURL}
conversationId: {conversationId}";
_logger.LogInformation(cred_str);
_logger.LogInformation($"Forwarding the following message to {toName}: {messageToSend}");
Dictionary<string, string> botCreds = GetBotCredentials();
// Create relevant accounts
ChannelAccount userAccount = new ChannelAccount(name: toName, id: toId);
ChannelAccount botAccount = new ChannelAccount(name: fromName, id: fromId);
if (!MicrosoftAppCredentials.IsTrustedServiceUrl(serviceURL))
{
_logger.LogInformation($"Adding to trusted service urls: {serviceURL}");
// Register the service URL as trusted
MicrosoftAppCredentials.TrustServiceUrl(serviceURL);
}
MicrosoftAppCredentials.TrustServiceUrl(serviceURL);
var account = new MicrosoftAppCredentials(botCreds["App ID"], botCreds["App Password"]);
var jwtToken = await account.GetTokenAsync();
ConnectorClient connector = new ConnectorClient(new System.Uri(serviceURL), account);
// Create a new message activity
IMessageActivity message = Activity.CreateMessageActivity();
conversationId = (
await connector
.Conversations
.CreateDirectConversationAsync(botAccount, userAccount)).Id;
// Set relevant message details
message.From = botAccount;
message.Recipient = userAccount;
message.Text = messageToSend;
message.Locale = "en-Us";
message.ChannelId = channelId;
// Create a new converstaion and add it to the message.
message.Conversation = new ConversationAccount(id: conversationId);
await connector.Conversations.SendToConversationAsync((Activity) message);
}
这是我的代码,用于收集上面使用的信息.当用户首次与漫游器进行交互时,会调用此函数.
And here is my code for gathering the information used above. This function gets called when the user first interacts with the bot.
/// <summary>
/// Called only when the !setup command is sent to the bot.
/// Updates the chats info in the DB.
/// </summary>
/// <param name="activity">Activity of the message the "!setup" command was sent in.</param>
/// <returns>True if the update query executed fine.</returns>
private bool SetupCommand(Activity activity)
{
// Connect to the database
this.database = new DBConnection(serverIP, databaseName, userName, password, _logger);
this.database.Connect();
var tableName = "ms_teams_chats";
// Data gathered from Activity for database.
// User ID
string toId = activity.From.Id;
// User Name
string toName = activity.From.Name;
// Bot ID
string fromId = activity.Recipient.Id;
// Bot Name
string fromName = activity.Recipient.Name;
// Users service URL
string serviceURL = activity.ServiceUrl;
// The platform the message came from. Example: 'skype'
string channelId = activity.ChannelId;
string conversationID = activity.Conversation.Id;
string conversationName = activity.Conversation.Name;
bool isGroupChat = activity.Conversation.IsGroup ?? false;
string upsertQuery = string.Empty;
upsertQuery = $@"
INSERT INTO {tableName}
(user_id, user_name, assoc_bot_id, assoc_bot_name, service_url, channel_id, conversation_id, is_group_chat)
VALUES (
'{toId}', '{toName}', '{fromId}', '{fromName}', '{serviceURL}', '{channelId}', '{conversationID}', {isGroupChat}
)
ON DUPLICATE KEY UPDATE
user_id = '{toId}',
user_name = '{toName}',
assoc_bot_id = '{fromId}',
assoc_bot_name = '{fromName}',
service_url = '{serviceURL}',
channel_id = '{channelId}',
conversation_id = '{conversationID}',
is_group_chat = {isGroupChat}
";
try
{
this.database.ExecuteNonQuery(upsertQuery);
}
catch (System.Exception e)
{
_logger.LogError($"Could not update users information. \nError:{e.ToString()}");
return false;
}
return true;
}
推荐答案
似乎您正在为上周遇到的同样问题而苦苦挣扎.似乎CreateDirectConversationAsync在MS Teams中不起作用,因为Teams也需要一个tennantId. 我在这里找到了关于此的声明: https://github.com/Microsoft/BotBuilder/issues/2944
It seems you are struggling with the same issue I had last week. it seems that the CreateDirectConversationAsync does not work in MS Teams as Teams also needs a tennantId. I found a statement about this here: https://github.com/Microsoft/BotBuilder/issues/2944
答案提到一个nuget软件包(Microsoft.Bot.Connector.Teams),该软件包在SDK的V4中不再可用.但是,正如我看到的那样,您已经从JSON输入中获取了一个sessionId,所以这应该不是问题.只需使用您在JSON中传递的sessionId即可. 如果您愿意这样做,您的代码可能类似于:
the answer mentions a nuget package (Microsoft.Bot.Connector.Teams) that is no longer available in V4 of the SDK. but as I see that you already got a conversationId from your JSON input, this should not be a problem. just use the conversationId you passed in the JSON. if you would do this, your code could look something like:
private static async Task SendProActiveMessgae()private async Task ForwardMessage(JToken forwardContext, string messageToSend)
{
// Collect data from JSON input
var restCmd = forwardContext;
var toId = (string) restCmd["toId"];
var toName = (string) restCmd["toName"];
var fromId = (string) restCmd["fromId"];
var fromName = (string) restCmd["fromName"];
var serviceURL = (string) restCmd["serviceURL"]
var conversationId = (string) restCmd["conversation"];
var uri = new Uri(serviceURL);
var appId = "APP ID";
var appSecret = "APP PASSWORD";
ConnectorClient connector = new ConnectorClient(uri, appId, appSecret);
var activity = new Activity()
{
Type = ActivityTypes.Message,
From = new ChannelAccount(fromId, fromName),
Recipient = new ChannelAccount(toId, toName),
Conversation = new ConversationAccount(false, "personal", conversationId),
Text = messageToSend
};
try
{
MicrosoftAppCredentials.TrustServiceUrl(serviceURL);
await connector.Conversations.SendToConversationAsync(conversationId, activity);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
这篇关于使用网络应用程序通过机器人主动发送消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!