/// <summary>
        /// Call Facebook Graph API with given set of parameters
        /// </summary>
        /// <param name="url"></param>
        /// <param name="sendSecretProof"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static dynamic FacebookApi(Method method, dynamic siteSettings, string url, object payload, bool sendSecretProof = false, bool throwOnError = false, params string[] queryStringPair)
        {
            RestClient  client = new RestClient("https://graph.facebook.com/");
            RestRequest req    = new RestRequest(url, method);

            // add parameters
            if (queryStringPair != null)
            {
                if (queryStringPair.Length % 2 != 0)
                {
                    throw new ArgumentOutOfRangeException("parameterPairs are not pairs");
                }

                for (int i = 0; i < queryStringPair.Length; i += 2)
                {
                    var key   = queryStringPair[i];
                    var value = queryStringPair[i + 1];

                    if (key == "access_token")
                    {
                        throw new ArgumentOutOfRangeException("access_token will be added automatically");
                    }

                    if (key == "appsecret_proof")
                    {
                        throw new ArgumentOutOfRangeException("appsecret_proof will be added automatically");
                    }

                    req.Parameters.Add(new Parameter()
                    {
                        Name  = key,
                        Value = value,
                        Type  = ParameterType.QueryString
                    });
                }
            }

            if (sendSecretProof)
            {
                string hash = MemoryCache.Default["FacebookMessengerModule.appsecret_proof"] as string;
                if (hash == null)
                {
                    hash = FacebookWebHook.HashHmac((string)siteSettings.FacebookMessenger.PageAccessToken,
                                                    (string)siteSettings.Application.FacebookAppSecret);

                    MemoryCache.Default["FacebookMessengerModule.appsecret_proof"] = hash;
                }
                req.AddQueryParameter("appsecret_proof", hash);
            }

            req.AddQueryParameter("access_token", (string)siteSettings.FacebookMessenger.PageAccessToken);

            if (payload is string)
            {
                req.AddParameter("payload", payload);
            }
            else
            {
                req.RequestFormat = DataFormat.Json;
                req.AddJsonBody(payload);
            }

            var response = client.Execute(req);

            if (response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                MailSenderModule.SendEmail("*****@*****.**", "Facebook API Post Error", response.ToString());

                if (throwOnError)
                {
                    throw new Exception("Server Returned: " + response.StatusCode);
                }
            }

            return(JObject.Parse(response.Content));
        }
        /// <summary>
        /// Call Facebook Graph API with given set of parameters
        /// </summary>
        /// <param name="url"></param>
        /// <param name="sendSecretProof"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static IEnumerable <dynamic> FacebookApiGet(dynamic siteSettings, string url, bool sendSecretProof = false, bool throwOnError = false, params string[] queryStringPair)
        {
            var client = new RestClient("https://graph.facebook.com/");
            var req    = new RestRequest(url, Method.GET);

            // add parameters
            if (queryStringPair != null)
            {
                if (queryStringPair.Length % 2 != 0)
                {
                    throw new ArgumentOutOfRangeException("parameterPairs are not pairs");
                }

                for (int i = 0; i < queryStringPair.Length; i += 2)
                {
                    var key   = queryStringPair[i];
                    var value = queryStringPair[i + 1];

                    if (key == "access_token")
                    {
                        throw new ArgumentOutOfRangeException("access_token will be added automatically");
                    }

                    if (key == "appsecret_proof")
                    {
                        throw new ArgumentOutOfRangeException("appsecret_proof will be added automatically");
                    }

                    req.Parameters.Add(new Parameter()
                    {
                        Name  = key,
                        Value = value,
                        Type  = ParameterType.QueryString
                    });
                }
            }

            if (sendSecretProof)
            {
                string hash = MemoryCache.Default["FacebookMessengerModule.appsecret_proof"] as string;
                if (hash == null)
                {
                    hash = FacebookWebHook.HashHmac((string)siteSettings.FacebookMessenger.PageAccessToken,
                                                    (string)siteSettings.Application.FacebookAppSecret);

                    MemoryCache.Default["FacebookMessengerModule.appsecret_proof"] = hash;
                }
                req.AddQueryParameter("appsecret_proof", hash);
            }

            req.AddQueryParameter("access_token", (string)siteSettings.FacebookMessenger.PageAccessToken);

LoadMore:

            var response = client.Execute(req);

            if (throwOnError && response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                throw new Exception("Server Returned: " + response.StatusCode);
            }

            dynamic result = JObject.Parse(response.Content);

            if (result.data != null)
            {
                foreach (var item in result.data)
                {
                    yield return(item);
                }
            }
            else
            {
                // this is a single item response
                yield return(result);
            }

            if (result.paging != null && result.paging.next != null)
            {
                req.AddQueryParameter("after", (string)result.paging.cursors.after);
                goto LoadMore;
            }
        }