private static void CommerceModule_PaymentSuccess(SaleOrder so, DatabaseSystem.NancyBlackDatabase db)
        {
            if (so.AffiliateCode == null)
            {
                return;
            }

            if (so.PaymentStatus != PaymentStatus.PaymentReceived)
            {
                return;
            }

            var existing = db.Query <AffiliateTransaction>().Where(t => t.SaleOrderId == so.Id).FirstOrDefault();

            if (existing != null)
            {
                return;
            }

            var registration = db.Query <AffiliateRegistration>()
                               .Where(r => r.AffiliateCode == so.AffiliateCode)
                               .FirstOrDefault();

            if (registration == null) // wrong code?
            {
                return;
            }

            if (registration.NcbUserId == so.NcbUserId)
            {
                return; // cannot self convert
            }

            // create a transaction
            AffiliateTransaction commission = new AffiliateTransaction();

            commission.AffiliateCode    = so.AffiliateCode;
            commission.CommissionAmount = Math.Floor(so.TotalAmount * registration.Commission);
            commission.SaleOrderId      = so.Id;

            commission.BTCAddress = registration.BTCAddress;
            db.UpsertRecord(commission);
            {
                var user = db.GetById <NcbUser>(registration.NcbUserId);
                if (user == null)
                {
                    return;
                }

                var    path      = Path.Combine(AffiliateModule.TemplatePath, "Affiliate-NewPaidOrder.html");
                string emailBody = File.ReadAllText(path);

                emailBody = emailBody.Replace("{{CommissionAmount}} ", commission.CommissionAmount.ToString("#,#"));
                emailBody = emailBody.Replace("{{Code}}", registration.AffiliateCode);

                MailSenderModule.SendEmail(user.Email, "We have new Sales thanks to you!", emailBody);
            }
        }
        /// <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);
        }
Exemple #3
0
        private dynamic HandlePasswordRequest(dynamic arg)
        {
            var registerParams = (arg.body.Value as JObject).ToObject <LoginParams>();

            var code = Guid.NewGuid().ToString();
            var user = this.SiteDatabase.Query <NcbUser>()
                       .Where(u => u.Email == registerParams.Email)
                       .FirstOrDefault();

            user.CodeRequestDate = DateTime.Now;
            user.Code            = code;
            this.SiteDatabase.UpsertRecord <NcbUser>(user);

            MailSenderModule.SendEmail(registerParams.Email,
                                       "Password Reset Request from: " + this.Request.Url.HostName,
                                       string.Format(@"Please click here to reset your password:<br/>
                      <a href=""http://{0}/__membership/resetpassword?code={1}"">http://{0}/__membership/resetpassword?code={1}</a>" + code
                                                     , this.Request.Url.HostName, code));

            return(200);
        }
Exemple #4
0
        private dynamic HandleNotifyForPayment(dynamic arg)
        {
            var id = ((JObject)arg.Body.Value).Value <string>("SaleOrderIdentifier");
            var so = this.SiteDatabase.Query <SaleOrder>()
                     .Where(row => row.SaleOrderIdentifier == id)
                     .FirstOrDefault();

            if (so == null)
            {
                return(404);
            }

            var siteSettings = this.SiteDatabase.Query <SiteSettings>().LastOrDefault();
            var setting      = JsonConvert.DeserializeObject <JObject>(siteSettings.js_SettingsJson);

            MailSenderModule.SendEmail(
                setting.Value <JObject>("smtp").Value <string>("fromEmail"),
                "Please Check Payment for Id : " + so.Id,
                string.Format(@"Site: {2} <br/>Please check customer payment:<br/>
                      <a href=""http://{0}/support/{1}"">http://{0}/support/{1}</a>",
                              this.Request.Url.HostName, so.SaleOrderIdentifier, setting.Value <JObject>("paysbuy").Value <string>("itm")));

            return(200);
        }
        /// <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));
        }
        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");
        }
        /// <summary>
        /// Handles the webhook
        /// </summary>
        public void HandleWebhook(NancyBlackDatabase db, dynamic siteSettings, dynamic messaging)
        {
            this.db           = db;
            this.sitesettings = siteSettings;

            if (this.Messages == null)
            {
                this.Messages = new List <dynamic>();
            }
            this.Messages.Add(messaging);

            if (messaging.optin != null)
            {
                string type     = (string)messaging.optin.@ref;
                var    isActive = FacebookWebHook.IsOptInActive(db,
                                                                this.NcbUserId, type);

                if (!isActive)
                {
                    db.UpsertRecord(new FacebookMessengerOptIn()
                    {
                        NcbUserId = this.NcbUserId,
                        OptInType = type
                    });
                }
            }

            if (messaging.message != null)
            {
                this.currentMessageText = messaging.message.text;

                if (messaging.message.quick_reply != null)
                {
                    this.currentQuickReply = messaging.message.quick_reply.payload;
                }
            }

            if (_Handlers == null)
            {
                _Handlers = new List <MethodInfo>();

                var methods = from m in this.GetType().GetMethods(BindingFlags.Public | BindingFlags.Static)
                              where
                              m.Name.StartsWith("Handle_") &&
                              m.ReturnType == typeof(bool) &&
                              m.GetParameters().Length == 2
                              orderby
                              m.Name
                              select m;

                foreach (var method in methods)
                {
                    _Handlers.Add(method);
                }
            }

            foreach (var handler in _Handlers)
            {
                try
                {
                    if (handler.GetCustomAttribute <ProcessEcho>() != null)
                    {
                        // method want to process echo - and this is not echo
                        if (messaging.message != null && messaging.message.is_echo == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        // method dont want echo - and this is echo
                        if (messaging.message != null && messaging.message.is_echo == true)
                        {
                            continue;
                        }
                    }

                    if (handler.GetCustomAttribute <RequireSessionData>() != null)
                    {
                        if (this.SessionData == null)
                        {
                            continue;
                        }
                    }

                    if (handler.GetCustomAttribute <RequireChatText>() != null)
                    {
                        if (string.IsNullOrEmpty(this.currentMessageText))
                        {
                            continue;
                        }
                    }

                    var requireOptin = handler.GetCustomAttribute <RequireOptin>();
                    if (requireOptin != null)
                    {
                        if (messaging.optin == null)
                        {
                            continue;
                        }

                        string input = messaging.optin.@ref;
                        if (input.StartsWith(requireOptin.ReferenceType) == false)
                        {
                            continue;
                        }
                    }

                    if (handler.GetCustomAttribute <RequireAttachments>() != null)
                    {
                        if (messaging.message.attachments == null)
                        {
                            continue;
                        }
                    }

                    var matchA = handler.GetCustomAttribute <MatchTextExactAttribute>();
                    if (matchA != null)
                    {
                        if (string.IsNullOrEmpty(this.currentMessageText))
                        {
                            continue;
                        }

                        bool matched = matchA.Text.Any(s => this.currentMessageText.ToLowerInvariant() == s.ToLowerInvariant());
                        if (matched == false)
                        {
                            continue;
                        }
                    }

                    var stateA = handler.GetCustomAttribute <StateAttribute>();
                    if (stateA != null)
                    {
                        if (string.IsNullOrEmpty(this.CurrentState))
                        {
                            continue;
                        }

                        bool stateMatched = stateA.State.Any(s => this.CurrentState == s || this.CurrentState.StartsWith(s));
                        if (stateMatched == false)
                        {
                            continue;
                        }
                    }

                    HandlerMethod d       = (HandlerMethod)Delegate.CreateDelegate(typeof(HandlerMethod), handler);
                    var           handled = d(this, messaging);
                    if (handled)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    MailSenderModule.SendEmail("*****@*****.**",
                                               "FacebookWebHook Handler Error",

                                               "<b>Facebook Input:</b><br/>" +
                                               messaging.ToString() + "<br/><br/>" +

                                               "<b>Message:</b>" + ex.Message + "<br/>" +
                                               ex.StackTrace);
                }
            }

            db.UpsertRecord(this);
        }
        public AffiliateModule()
        {
            AffiliateModule.TemplatePath = Path.Combine(RootPath, "Site", "Views", "EmailTemplates");

            Post["/__affiliate/apply"] = HandleRequest((arg) =>
            {
                if (this.CurrentUser.IsAnonymous)
                {
                    return(400);
                }

                var body = arg.body.Value;

                var currentUser = AffiliateModule.ApplyAffiliate(this.SiteDatabase, this.CurrentUser.Id, (string)body.source);
                AffiliateModule.UpdateReferer(this.SiteDatabase, this.CurrentUser.Id, (string)body.source);

                var regresult = JObject.FromObject(currentUser);

                if (body.sharedCoupon != null)
                {
                    var discountCode = (string)body.sharedCoupon.CouponCode;

                    lock (BaseModule.GetLockObject("SharedCouponCheck-" + currentUser.Id))
                    {
                        // original coupon
                        var claim = this.SiteDatabase.Query <AffiliateRewardsClaim>()
                                    .Where(c => c.DiscountCode == discountCode)
                                    .OrderBy(c => c.Id)
                                    .FirstOrDefault();

                        // owner of the coupon
                        var couponOwner = this.SiteDatabase.Query <AffiliateRegistration>()
                                          .Where(r => r.NcbUserId == claim.NcbUserId)
                                          .FirstOrDefault();

                        System.Action performShare = () =>
                        {
                            // prevent dubplicates
                            var existing = this.SiteDatabase.Query <AffiliateRewardsClaim>()
                                           .Where(c => c.DiscountCode == discountCode && c.AffiliateRegistrationId == currentUser.Id)
                                           .FirstOrDefault();

                            if (existing != null)
                            {
                                // already has this coupon
                                regresult.Add("CouponSaved", true);

                                return;
                            }

                            var toCopy = this.SiteDatabase.GetById <AffiliateRewardsClaim>((int)body.sharedCoupon.CouponId);

                            toCopy.Id = 0;
                            toCopy.AffiliateRegistrationId = currentUser.Id;
                            toCopy.AffiliateCode           = currentUser.AffiliateCode;
                            toCopy.NcbUserId      = this.CurrentUser.Id;
                            toCopy.RewardsName    = "shared from ID:" + body.sharedCoupon.AffiliateId;
                            toCopy.IsShareEnabled = false;

                            this.SiteDatabase.UpsertRecord(toCopy);
                        };

                        var ownerAncestors = AffiliateModule.DiscoverUpline(couponOwner.AffiliateCode, this.SiteDatabase);

                        // same user, cannot share
                        if (couponOwner.Id == currentUser.Id)
                        {
                            regresult.Add("CouponSaved", false);
                            regresult.Add("Message", "SAME_USER");
                            regresult.Add("Owner", couponOwner.AffiliateName);
                        }
                        else if (couponOwner.RefererAffiliateCode == currentUser.AffiliateCode)
                        {
                            // owner is direct downline of current user
                            // meaning current user trying to get coupon from direct downline
                            // this is not allowed

                            regresult.Add("CouponSaved", false);
                            regresult.Add("Message", "SAME_TREE");
                            regresult.Add("Owner", couponOwner.AffiliateName);
                        }
                        else if (currentUser.RefererAffiliateCode == couponOwner.AffiliateCode)
                        {
                            // owner is upline of current user
                            // can share coupon
                            performShare();
                        }
                        else if (ownerAncestors.Contains(currentUser.AffiliateCode))
                        {
                            // current user is an ancestor of coupon owner,
                            // allow sharing but we keep track
                            MailSenderModule.SendEmail("*****@*****.**",
                                                       "Tricky Sharing Coupon Behavior Detected",
                                                       "Affiliate:" + couponOwner.AffiliateCode + " trying to share coupon to: " + currentUser.AffiliateCode +
                                                       "But " + currentUser.AffiliateCode + " is also ancestor of the person who own coupons." +
                                                       "Distance between affiliate is: " + ownerAncestors.IndexOf(currentUser.AffiliateCode) + " Levels",
                                                       false,
                                                       this.Context);


                            performShare();
                        }
                        else
                        {
                            // there is no relationship between  owner and current user, can share
                            performShare();
                        }
                    }
                }

                if (body.sharedReward != null)
                {
                    lock (BaseModule.GetLockObject("SharedRewardCheck-" + currentUser.Id))
                    {
                        var result = AffiliateReward.ClaimReward(this.SiteDatabase, (int)body.sharedReward.Id, currentUser.Id);
                        if (result != null)
                        {
                            regresult.Add("RewardClaimed", true);
                        }
                    }
                }

                return(regresult);
            });

            Post["/__affiliate/requestpayment"] = HandleRequest((arg) =>
            {
                if (CurrentUser.IsAnonymous)
                {
                    return(400);
                }

                var registration = SiteDatabase.Query <AffiliateRegistration>()
                                   .Where(t => t.NcbUserId == CurrentUser.Id).FirstOrDefault();

                if (registration == null)
                {
                    return(400);
                }

                var pendingPayment = SiteDatabase.Query <AffiliateTransaction>()
                                     .Where(t => t.AffiliateCode == registration.AffiliateCode && t.IsCommissionPaid == false && t.IsPendingApprove == false)
                                     .ToList();


                // using alternate rate
                SiteDatabase.Transaction(() =>
                {
                    foreach (var item in pendingPayment)
                    {
                        item.IsPendingApprove = true;
                        SiteDatabase.UpsertRecord(item);
                    }
                });

                return(200);
            });

            Post["/__affiliate/claimrewards"] = HandleRequest((arg) =>
            {
                dynamic param = (arg.body.Value as JObject);
                if (param.Id == null)
                {
                    return(400);
                }

                var registration = AffiliateModule.ApplyAffiliate(this.SiteDatabase, this.CurrentUser.Id);

                var result = AffiliateReward.ClaimReward(this.SiteDatabase, (int)param.Id, registration.Id);
                if (result == null)
                {
                    return(403);
                }

                return(result);
            });

            Post["/__affiliate/addtosaleorder"] = HandleRequest((arg) =>
            {
                if (CurrentUser.IsAnonymous)
                {
                    return(400);
                }

                var requestBody             = (arg.body.Value as JObject);
                var saleOrderId             = requestBody.Value <int>("saleOrderId");
                var affiliateRewardsClaimId = requestBody.Value <int>("arcId");

                if (saleOrderId != 0 && affiliateRewardsClaimId != 0)
                {
                    var aRC = SiteDatabase.GetById <AffiliateRewardsClaim>(affiliateRewardsClaimId);

                    if (aRC.IncludedInSaleOrderId != 0 || aRC.DiscountCode != null)
                    {
                        return(403);
                    }

                    aRC.IncludedInSaleOrderId = saleOrderId;
                    SiteDatabase.UpsertRecord(aRC);

                    return(new
                    {
                        AffiliateRewardsClaim = aRC
                    });
                }


                return(403);
            });

            Post["/__affiliate/updateprofile"] = HandleRequest((arg) =>
            {
                var requestBody = arg.body.Value;

                if (requestBody.Profile == null && requestBody.Registration == null)
                {
                    return(400);
                }

                // Impersonation in effect
                int userId = this.CurrentUser.Id;
                if (userId != (int)requestBody.UserId)
                {
                    if (userId == 1)
                    {
                        userId = (int)requestBody.UserId;
                    }
                    else
                    {
                        return(400); // user that is not 1 cannot save with impersonation
                    }
                }

                if (requestBody.Profile != null)
                {
                    UserManager.Current.UpdateProfile(this.SiteDatabase, userId, requestBody.Profile);
                }

                if (requestBody.Registration != null)
                {
                    AffiliateRegistration registration = SiteDatabase.Query <AffiliateRegistration>()
                                                         .Where(t => t.NcbUserId == CurrentUser.Id).FirstOrDefault();

                    registration.AffiliateName    = requestBody.Registration.AffiliateName;
                    registration.AffiliateMessage = requestBody.Registration.AffiliateMessage;
                    SiteDatabase.UpsertRecord(registration);

                    MemoryCache.Default.Remove("AffiliateReg-" + registration.AffiliateCode);
                }

                MemoryCache.Default.Remove("dashboard-" + CurrentUser.Id);


                return(200);
            });

            Get["/" + AFFILIATE_PROGRAM_NAME + "/dashboard"] = HandleRequest((arg) =>
            {
                if (this.CurrentUser.IsAnonymous)
                {
                    return(this.Response.AsRedirect("/" + AFFILIATE_PROGRAM_NAME));
                }

                var id = this.CurrentUser.Id;
                AffiliateRegistration registration = null;

                if (this.CurrentUser.HasClaim("admin") && Request.Query.code != null) // admin impersonate anyone
                {
                    var code     = (string)Request.Query.code;
                    registration = SiteDatabase.Query <AffiliateRegistration>()
                                   .Where(t => t.AffiliateCode == code).FirstOrDefault();

                    if (registration == null)
                    {
                        return(404); // wrong code
                    }
                }
                else if (this.CurrentUser.HasClaim("admin") && Request.Query.so != null)
                {
                    var soId = (int)Request.Query.so;
                    var so   = SiteDatabase.GetById <SaleOrder>(soId);

                    if (so.NcbUserId == 0)
                    {
                        return(404); // user cannot view squad51 because they was not registered
                    }

                    registration = SiteDatabase.Query <AffiliateRegistration>()
                                   .Where(t => t.NcbUserId == so.NcbUserId).FirstOrDefault();

                    // automatically apply owner of given so
                    if (registration == null &&
                        (so.PaymentStatus == PaymentStatus.PaymentReceived ||
                         so.PaymentStatus == PaymentStatus.Deposit))
                    {
                        registration = AffiliateModule.ApplyAffiliate(this.SiteDatabase, so.NcbUserId);
                    }
                }
                else
                {
                    if (id != 0)
                    {
                        registration = SiteDatabase.Query <AffiliateRegistration>()
                                       .Where(t => t.NcbUserId == id).FirstOrDefault();
                    }
                }

                if (registration == null)
                {
                    if (id != 0) // some known user but we still can't get their registration
                    {
                        // no registration - try to see whether this user already a customer
                        var saleOrder = this.SiteDatabase.Query <SaleOrder>()
                                        .Where(so => so.NcbUserId == id &&
                                               (so.PaymentStatus == PaymentStatus.Deposit ||
                                                so.PaymentStatus == PaymentStatus.PaymentReceived))
                                        .FirstOrDefault();

                        // already customer - auto register them
                        if (saleOrder != null)
                        {
                            registration = AffiliateModule.ApplyAffiliate(this.SiteDatabase, id);
                            return(this.AffiliateDashboard(registration, arg));
                        }
                    }

                    // redirect back to application page
                    return(this.Response.AsRedirect("/" + AFFILIATE_PROGRAM_NAME));
                }


                return(this.AffiliateDashboard(registration, arg));
            });

            Get["/" + AFFILIATE_PROGRAM_NAME] = HandleRequest((arg) =>
            {
                var id = this.CurrentUser.Id;

                AffiliateRegistration registration = SiteDatabase.Query <AffiliateRegistration>()
                                                     .Where(t => t.NcbUserId == id).FirstOrDefault();

                var content = ContentModule.GetPage(SiteDatabase, "/__affiliate", true);
                return(View["affiliate-apply", new StandardModel(this, content, new
                {
                    Registration = registration
                })]);
            });

            Get["/__affiliate/profileimage/{id}"] = this.HandleRequest(arg =>
            {
                var response         = new Response();
                response.ContentType = "image/jpeg";
                response.Contents    = (output) =>
                {
                    WebClient client = new WebClient();
                    var data         = client.DownloadData("https://graph.facebook.com/" + (string)arg.id + "/picture?type=large");
                    output.Write(data, 0, data.Length);
                };
                return(response);
            });

            Get["/__affiliate/getsharedcoupon"] = this.HandleRequest((arg) =>
            {
                if (this.Request.Cookies.ContainsKey("coupon"))
                {
                    var id     = this.Request.Cookies["coupon"];
                    var coupon = this.SiteDatabase.GetById <AffiliateRewardsClaim>(int.Parse(id));

                    if (coupon != null)
                    {
                        if (coupon.IsShareEnabled == false)
                        {
                            return(404);
                        }

                        var couponProduct = this.SiteDatabase.GetById <Product>(coupon.ProductId);
                        if (couponProduct.Url.Contains("/archive/"))
                        {
                            return(new {
                                IsValid = false,
                                Message = "USED"
                            });
                        }

                        var reg = this.SiteDatabase.GetById <AffiliateRegistration>(coupon.AffiliateRegistrationId);

                        if (this.CurrentUser.IsAnonymous == false)
                        {
                            // prevent referee to share coupon back to referer
                            var currentUser = AffiliateModule.ApplyAffiliate(this.SiteDatabase, this.CurrentUser.Id);
                            if (reg.RefererAffiliateCode == currentUser.AffiliateCode)
                            {
                                return(new
                                {
                                    IsValid = false,
                                    Message = "SAME_TREE"
                                });
                            }
                        }

                        return(new
                        {
                            AffiliateId = reg.Id,
                            AffiliateName = reg.AffiliateName,
                            AffiliateRewardsId = coupon.AffiliateRewardsId,
                            CouponId = coupon.Id,
                            CouponCode = coupon.DiscountCode,
                            CouponAttributes = coupon.CouponAttributes
                        });
                    }
                }

                return(404);
            });

            Get["/__affiliate/getreward"] = this.HandleRequest((arg) =>
            {
                if (this.Request.Cookies.ContainsKey("reward"))
                {
                    var id     = this.Request.Cookies["reward"];
                    var reward = this.SiteDatabase.GetById <AffiliateReward>(int.Parse(id));

                    if (reward != null)
                    {
                        if (reward.IsDirectClaim == false)
                        {
                            return(404);
                        }

                        if (reward.IsRewardsClaimable == false)
                        {
                            return(new
                            {
                                IsValid = false
                            });
                        }

                        return(reward);
                    }
                }

                return(404);
            });

            Get["/__affiliate/myrewards"] = this.HandleRequest((arg) =>
            {
                if (this.CurrentUser.IsAnonymous)
                {
                    return(401);
                }

                return(this.SiteDatabase.Query <AffiliateRewardsClaim>()
                       .Where(c => c.NcbUserId == this.CurrentUser.Id)
                       .AsEnumerable());
            });
        }