使用Azure的Facebook Messenger机器人主动/推送通知
我正在使用Microsoft bot框架为Facebook Messenger构建一个bot。我计划使用CosmosDB进行状态管理,也作为我的后端数据存储。(我不喜欢CosmosBD,如果需要,我可以使用任何其他商店) 我需要根据用户的时间偏好向他们发送每日/每周主动消息(推送通知)。当他们第一次与机器人交互时,我将捕获他们的时间偏好 传递这些通知的最佳方式是什么 由于我将在CosmosDB中存储这些首选项,我正在考虑根据用户时间首选项来使用和安排它。此Azure函数将调用my webhook,它将传递这些消息。如果需要,我将在用户更改其偏好时更改功能计划 我的问题是:使用Azure的Facebook Messenger机器人主动/推送通知,facebook,azure,botframework,azure-functions,facebook-messenger-bot,Facebook,Azure,Botframework,Azure Functions,Facebook Messenger Bot,我正在使用Microsoft bot框架为Facebook Messenger构建一个bot。我计划使用CosmosDB进行状态管理,也作为我的后端数据存储。(我不喜欢CosmosBD,如果需要,我可以使用任何其他商店) 我需要根据用户的时间偏好向他们发送每日/每周主动消息(推送通知)。当他们第一次与机器人交互时,我将捕获他们的时间偏好 传递这些通知的最佳方式是什么 由于我将在CosmosDB中存储这些首选项,我正在考虑根据用户时间首选项来使用和安排它。此Azure函数将调用my webhook
提前谢谢。您可能需要检查FB关于主动消息的政策 有一个24小时的限制,但在你的情况下,它可能不会完全搞砸
我在FramWork和messenger中广泛使用pro-active dialog,没有任何问题。在facebook审批过程中,您只需通知他们您将通过messenger和您的机器人发送通知。通常,如果你用它来通知你的用户,远离促销内容,你应该会没事的 我还使用azure函数从自定义控制器端点触发主动对话 下面是azure函数的示例代码: 下面是启动“主动”对话框的示例代码:
公共静态异步任务恢复(字符串恢复cookie),其中T:IDialog,new()
{
//反序列化对会话的引用
ConversationReference ConversationReference=JsonConvert.DeserializeObject(resumptionCookie);
//从bot向用户生成消息
var message=conversationReference.GetPostToBotMessage();
var builder=new ContainerBuilder();
使用(var scope=DialogModule.BeginLifetimeScope(Conversation.Container,message))
{
//从冷启动开始,该服务尚未通过dev bot azure服务进行身份验证
//因此,我们必须信任端点url。
如果(!MicrosoftAppCredentials.IsTrustedServiceUrl(message.ServiceUrl))
{
MicrosoftAppCredentials.TrustServiceUrl(message.ServiceUrl,DateTime.MaxValue);
}
var botData=scope.Resolve();
等待botData.LoadAsync(CancellationToken.None);
//这是我们的对话框堆栈
var task=scope.Resolve();
T dialog=scope.Resolve();//使用autofac解析对话框
尝试
{
task.Call(dialog.Void(),null);
wait task.PollAsync(CancellationToken.None);
}
捕获(例外情况除外)
{
//待办事项日志
}
最后
{
//刷新对话框堆栈
等待botData.FlushAsync(CancellationToken.None);
}
}
}
您的对话框需要在autofac中注册。
您的resumptionCookie需要保存在数据库中 首先,我认为这里没有任何“正确”的答案;这将在很大程度上取决于您所在领域的特定需求。规模将在这一设计中发挥重要作用。你会有100个用户吗?一万用户?1mil用户?我假设你想设计一个最大规模的前端,但这可能有点过头了 首先,根据您所描述的,我认为CosmosDB触发器不一定是问题的解决方案,因为只有在创建/更新首选项数据时才会触发。我假设,从那一点开始,你的函数需要在他们选择的时间段持续启动,对吗 让我们假设你让人们从一天中的24小时中进行选择。一种幼稚的方法是简单地使用一个每小时触发一次的定时触发器,查询CosmosDB以查找偏好设置为该特定小时的所有文档,然后从那里开始发送通知。问题是如何从那里扩展并在失败面前处理幂等性问题 首先,计时器触发器只能启动一个实例。如果您只是去查询CosmosDB文档,并开始在单个触发器的范围内逐个处理它们,那么您可以相对快速地达到可以扩展到多少通知的上限。相反,您要做的是使用计时器触发器将通知扇出到尽可能多的“工作者”函数实例。计时器触发器可以充当编排器,因为它可以拥有针对CosmosDB的查询,然后将它为特定通知时间窗口找到的每个文档结果转换为一条消息,并将其放置在队列上,由单独的函数处理,该函数将自行扩展 实际上,有几种方法可以通过Azure功能实现这一点,这实际上取决于您对技术的早期采用感到满意的程度 第一种是我称之为“手动”的方式,它只需使用现有的Azure存储队列扩展,将
IAsyncCollector
作为绑定到工作队列的计时器函数的参数,然后通过该参数输出消息。然后编写第二个伴随函数,该函数使用QueueTrigger
,将其绑定到同一队列,它将负责处理每条消息。第二个函数是您获得缩放的地方,启用所有
public static void Run(TimerInfo notificationTrigger, TraceWriter log)
{
try
{
//Serialize request object
string timerInfo = JsonConvert.SerializeObject(notificationTrigger);
//Create a request for bot service with security token
HttpRequestMessage hrm = new HttpRequestMessage()
{
Method = HttpMethod.Post,
RequestUri = new Uri(NotificationEndPointUrl),
Content = new StringContent(timerInfo, Encoding.UTF8, "application/json")
};
hrm.Headers.Add("Authorization", NotificationApiKey);
log.Info(JsonConvert.SerializeObject(hrm));
//Call service
using (var client = new HttpClient())
{
Task task = client.SendAsync(hrm).ContinueWith((taskResponse) =>
{
HttpResponseMessage result = taskResponse.Result;
var jsonString = result.Content.ReadAsStringAsync();
jsonString.Wait();
if (result.StatusCode != System.Net.HttpStatusCode.OK)
{
//Throw what ever problem as an exception with details
throw new Exception($"AzureFunction - ERRROR - HTTP {result.StatusCode}");
}
});
task.Wait();
}
}
catch (Exception ex)
{
//TODO log
}
}