Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Azure的Facebook Messenger机器人主动/推送通知_Facebook_Azure_Botframework_Azure Functions_Facebook Messenger Bot - Fatal编程技术网

使用Azure的Facebook Messenger机器人主动/推送通知

使用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

我正在使用Microsoft bot框架为Facebook Messenger构建一个bot。我计划使用CosmosDB进行状态管理,也作为我的后端数据存储。(我不喜欢CosmosBD,如果需要,我可以使用任何其他商店)

我需要根据用户的时间偏好向他们发送每日/每周主动消息(推送通知)。当他们第一次与机器人交互时,我将捕获他们的时间偏好

传递这些通知的最佳方式是什么

由于我将在CosmosDB中存储这些首选项,我正在考虑根据用户时间首选项来使用和安排它。此Azure函数将调用my webhook,它将传递这些消息。如果需要,我将在用户更改其偏好时更改功能计划

我的问题是:

  • 这是一个好方法吗
  • 是否有其他替代方案(通知中心?)
  • 我应该能够为通知设置特定的时间(比如在一个小时的顶部或类似的时间),安排Azure函数在这些时间运行而不是根据用户偏好创建函数是否有意义(我实际上也可以结合这两种方法)

  • 提前谢谢。

    您可能需要检查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
        }
    }