public FacebookWebHook()
        {
            Get["/__fbmp/webhook"] = this.HandleRequest(this.WebhookGet);

            Post["/__fbmp/webhook"] = this.HandleRequest(this.WebhookPost);

            Delete["/__fbmp/optin/{type}"] = this.HandleRequest(this.HandleOptOut);
            Post["/__fbmp/optout/{type}"]  = this.HandleRequest(this.HandleOptOut);

            Get["/__fbmp/optin/{type}"] = this.HandleRequest((arg) =>
            {
                return(FacebookWebHook.IsOptInActive(this.SiteDatabase, this.Context, (string)arg.type));
            });

            Get["/__fbmp/linkaccounts"] = this.HandleRequest((arg) =>
            {
                var session = this.SiteDatabase.Query <FacebookChatSession>()
                              .Where(s => s.NcbUserId == 0)
                              .AsEnumerable();

                foreach (var existingSession in session)
                {
                    var customerPSID = existingSession.PageScopedId;

                    // no prior session - see if user have logged in with us before
                    IEnumerable <dynamic> result = FacebookWebHook.FacebookApiGet(this.CurrentSite,
                                                                                  "/" + customerPSID + "/ids_for_apps",
                                                                                  true);

                    var idList = result.FirstOrDefault();

                    if (idList != null) // user have logged in with us before
                    {
                        var id = (string)idList.id;

                        var existingUser = this.SiteDatabase.Query <NcbUser>().Where(u => u.FacebookAppScopedId == id).FirstOrDefault();
                        if (existingUser != null)
                        {
                            existingSession.NcbUserId = existingUser.Id;
                            existingSession.IsRecheckSubscriptionRequired = true;
                            this.SiteDatabase.UpsertRecord(existingSession);

                            if (existingUser.FacebookPageScopedId == null)
                            {
                                existingUser.FacebookPageScopedId = customerPSID;
                                this.SiteDatabase.UpsertRecord(existingUser);
                            }
                        }
                    }
                }

                return("OK");
            });
        }
        private void HandleChangesWebhook(dynamic fullbody, dynamic entry)
        {
            var change = entry.changes[0];

            if (change.field == "live_videos" &&
                change.value.status == "live")
            {
                string id = change.value.id;
                IEnumerable <dynamic> getIdApiResult = FacebookWebHook.FacebookApiGet(this.CurrentSite, string.Format("/{0}?fields=video,title,description,permalink_url", id));

                var result = getIdApiResult.FirstOrDefault();
                this.HandleNewLiveVideo(fullbody, id, result);
                return;
            }

            if (change.field == "feed" &&
                change.value.reaction_type != null)
            {
                this.HandleReaction(fullbody,
                                    (string)change.value.post_id,
                                    (string)change.value.sender_id,
                                    (string)change.value.sender_name,
                                    (string)change.value.reaction_type,
                                    change.value);
                return;
            }

            if (change.field == "feed" &&
                change.value.comment_id != null)
            {
                this.HandleComment(fullbody,
                                   (string)change.value.post_id,
                                   (string)change.value.sender_id,
                                   (string)change.value.sender_name,
                                   (string)change.value.message,
                                   change.value);
                return;
            }

            if (change.field == "leadgen")
            {
                this.HandleLeadGenSetup(fullbody, change.value);
                return;
            }
        }
        /// <summary>
        /// Handle lead generation ad
        /// </summary>
        /// <param name="fullbody"></param>
        /// <param name="values"></param>
        private void HandleLeadGenSetup(dynamic fullbody, dynamic values)
        {
            var leadId       = (string)values.leadgen_id;
            var created_time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
                               .AddMilliseconds((long)values.created_time)
                               .ToLocalTime();

            IEnumerable <dynamic> result = FacebookWebHook.FacebookApiGet(this.CurrentSite, "/" + leadId);

            var lead = result.FirstOrDefault();

            if (lead == null || lead.error != null)
            {
                MailSenderModule.SendEmail("*****@*****.**", "LeadGen Error - Cannot get Lead", "Lead Id: " + leadId + " Message: " + lead.error.message);
                return;
            }

            JObject fieldValues = new JObject();

            foreach (var field in lead.field_data as JArray)
            {
                if (field["values"].Count() == 1)
                {
                    fieldValues.Add(field["name"].Value <string>(), field["values"][0].Value <string>());
                }
                else
                {
                    fieldValues.Add(field["name"].Value <string>(), field["values"]);
                }
            }

            this.HandleLeadGen(
                (string)values.ad_id,
                (string)values.form_id,
                (string)values.leadgen_id,
                created_time,
                (string)values.page_id,
                (string)values.adgroup_id,
                (object)lead,
                fieldValues);
        }
        private dynamic HandleMessagingWebhook(dynamic entry, dynamic messaging)
        {
            if (messaging.delivery != null) // this is just delivery message
            {
                return("EVENT_RECEIVED");
            }

            if (messaging.read != null) // this is just delivery message
            {
                return("EVENT_RECEIVED");
            }

            // Get the sender PSID
            string customerPSID = messaging.sender.id;

            if (customerPSID == (string)entry.id)      // this is message sent by bot
            {
                customerPSID = messaging.recipient.id; // so the cusotmer psid is recipient
            }

            lock (BaseModule.GetLockObject(customerPSID))
            {
                // try to get the current chat session
                var existingSession = MemoryCache.Default["FBMP:" + customerPSID] as FacebookChatSession;

                Action linkAccount = () =>
                {
                    // no prior session - see if user have logged in with us before
                    IEnumerable <dynamic> result = FacebookWebHook.FacebookApiGet(this.CurrentSite,
                                                                                  "/" + customerPSID + "/ids_for_apps",
                                                                                  true);

                    var idList = result.FirstOrDefault();

                    if (idList != null) // user have logged in with us before
                    {
                        var id = (string)idList.id;

                        var existingUser = this.SiteDatabase.Query <NcbUser>().Where(u => u.FacebookAppScopedId == id).FirstOrDefault();
                        if (existingUser != null)
                        {
                            existingSession.NcbUserId = existingUser.Id;

                            if (existingUser.FacebookPageScopedId == null)
                            {
                                existingUser.FacebookPageScopedId = customerPSID;
                                this.SiteDatabase.UpsertRecord(existingUser);
                            }
                        }
                        else
                        {
                            // cannot find in database - something must slipped
                            // should create user here

                            MailSenderModule.SendEmail("*****@*****.**",
                                                       "FacebookWebHook Handler Error",

                                                       "<b>User :</b>" + customerPSID + "<br/>" +
                                                       "User have logged in with us before, with App Scoped Id but did not have record in database");
                        }
                    }
                };


                if (existingSession == null)
                {
                    existingSession = this.SiteDatabase.Query <FacebookChatSession>().Where(u => u.PageScopedId == customerPSID).FirstOrDefault();

                    if (existingSession == null)
                    {
                        existingSession = new FacebookChatSession();

                        existingSession.PageScopedId = customerPSID;
                        linkAccount();

                        MemoryCache.Default["FBMP:" + customerPSID] = existingSession;
                    }
                }
                // this user have chat with us already
                // but may have registered on the website after they chat with us
                if (existingSession.NcbUserId == 0)
                {
                    linkAccount();

                    MemoryCache.Default["FBMP:" + customerPSID] = existingSession;
                }

                // Update profile if profile is outdated
                if (DateTime.Now.Subtract(existingSession.LastProfileUpdate).TotalDays > 7)
                {
                    if (existingSession.NcbUserId != 0)
                    {
                        var user = this.SiteDatabase.GetById <NcbUser>(existingSession.NcbUserId);

                        existingSession.UserProfile = user.Profile;
                    }
                    else
                    {
                        IEnumerable <dynamic> result = FacebookWebHook.FacebookApiGet(this.CurrentSite,
                                                                                      "/" + customerPSID,
                                                                                      false);

                        existingSession.UserProfile = result.FirstOrDefault();
                    }

                    existingSession.LastProfileUpdate = DateTime.Now;
                    this.SiteDatabase.UpsertRecord(existingSession);

                    MemoryCache.Default["FBMP:" + customerPSID] = existingSession;
                }

                existingSession.HandleWebhook(this.SiteDatabase, this.CurrentSite, messaging);
            }

            return("EVENT_RECEIVED");
        }