예제 #1
0
        /// <summary>
        /// Execute async Delivery request
        /// </summary>
        /// <param name="request">Target Delivery request</param>
        /// <returns>Target Delivery Response</returns>
        internal Task <TargetDeliveryResponse> ExecuteRequestAsync(TargetDeliveryRequest request)
        {
            this.SetUrl(this.GetLocationHint(request));
            Telemetry.AddTelemetry(request.DeliveryRequest, this.clientConfig);
            this.logger.LogRequest(request);
            var executeTask = this.deliveryApi.ExecuteAsync(this.clientConfig.OrganizationId, request.SessionId, request.DeliveryRequest);

            return(executeTask.ContinueWith(task => this.GetTargetDeliveryResponse(request, task.Result), TaskScheduler.Default));
        }
예제 #2
0
        /// <summary>
        /// Execute sync Delivery request
        /// </summary>
        /// <param name="request">Target Delivery request</param>
        /// <returns>Target Delivery Response</returns>
        internal TargetDeliveryResponse ExecuteRequest(TargetDeliveryRequest request)
        {
            this.SetUrl(this.GetLocationHint(request));
            Telemetry.AddTelemetry(request.DeliveryRequest, this.clientConfig);
            this.logger.LogRequest(request);
            var response = this.deliveryApi.Execute(this.clientConfig.OrganizationId, request.SessionId, request.DeliveryRequest);

            return(this.GetTargetDeliveryResponse(request, response));
        }
        public Dictionary <string, object> CollateParams(TargetDeliveryRequest deliveryRequest = default, RequestDetails requestDetails = default)
        {
            var result   = new Dictionary <string, object>();
            var dateTime = TimeProvider.Current.UtcNow;

            result.Add(CurrentTimestamp, new DateTimeOffset(dateTime).ToUnixTimeMilliseconds());
            result.Add(CurrentDay, dateTime.DayOfWeek == 0 ? 7 : (int)dateTime.DayOfWeek);
            result.Add(CurrentTime, dateTime.ToString("HHmm"));
            return(result);
        }
예제 #4
0
        private TargetDeliveryResponse GetTargetDeliveryResponse(TargetDeliveryRequest request, DeliveryResponse response)
        {
            if (response == null)
            {
                return(new TargetDeliveryResponse(request, null, HttpStatusCode.ServiceUnavailable));
            }

            this.UpdateStickyLocationHint(response);
            this.logger.LogResponse(response);
            return(new TargetDeliveryResponse(request, ConvertResponseOptions(response), (HttpStatusCode)response.Status));
        }
예제 #5
0
        private static TargetDeliveryRequest AddMBoxesToRequest(TargetDeliveryRequest request, params string[] mboxes)
        {
            if (request?.DeliveryRequest == null)
            {
                request = new TargetDeliveryRequest.Builder()
                          .SetDecisioningMethod(DecisioningMethod.Hybrid)
                          .SetContext(new Context(ChannelType.Web))
                          .Build();
            }

            if (mboxes == null || mboxes.Length == 0)
            {
                return(request);
            }

            var existingMboxNames = new HashSet <string>();
            var index             = 0;

            var deliveryRequest = request.DeliveryRequest;
            var prefetchMboxes  = deliveryRequest.Prefetch?.Mboxes ?? new List <MboxRequest>();

            existingMboxNames.UnionWith(prefetchMboxes.Select(mbox => mbox.Name));

            var executeMboxes = deliveryRequest.Execute?.Mboxes ?? new List <MboxRequest>();

            executeMboxes.ForEach(mbox =>
            {
                if (mbox.Index >= index)
                {
                    index = (int)mbox.Index + 1;
                }

                existingMboxNames.Add(mbox.Name);
            });

            deliveryRequest.Execute ??= new ExecuteRequest();
            deliveryRequest.Execute.Mboxes ??= new List <MboxRequest>();

            foreach (var mbox in mboxes)
            {
                if (existingMboxNames.Contains(mbox))
                {
                    continue;
                }

                deliveryRequest.Execute.Mboxes.Add(new MboxRequest(name: mbox, index: index++));
            }

            return(request);
        }
예제 #6
0
        internal static void AddTelemetry(this TargetDeliveryRequest request, TargetClientConfig config, int?execution = default)
        {
            var telemetryEntry = request.GetTelemetryEntry(config, execution);

            if (telemetryEntry == null)
            {
                return;
            }

            var deliveryRequest = request.DeliveryRequest;

            deliveryRequest.Telemetry ??= new Delivery.Model.Telemetry(new List <TelemetryEntry>());
            deliveryRequest.Telemetry.Entries.Add(telemetryEntry);
        }
예제 #7
0
        internal static void ValidateSendNotifications(TargetDeliveryRequest deliveryRequest)
        {
            var request = deliveryRequest?.DeliveryRequest;

            if (request == null)
            {
                throw new ArgumentNullException(nameof(deliveryRequest));
            }

            if (request.Notifications == null || request.Notifications.Count == 0)
            {
                throw new ValidationException(Messages.NotificationsRequired);
            }
        }
예제 #8
0
 internal TraceHandler(
     TargetClientConfig clientConfig,
     IRuleLoader ruleLoader,
     OnDeviceDecisioningRuleSet ruleSet,
     TargetDeliveryRequest request)
 {
     this.ruleSet = ruleSet;
     this.trace   = new Dictionary <string, object>
     {
         { ClientCodeKey, clientConfig.Client },
         { ArtifactKey, this.ArtifactTrace(ruleLoader) },
         { ProfileKey, ProfileTrace(request.DeliveryRequest.Id) },
     };
     this.campaigns        = new Dictionary <long, IDictionary <string, object> >();
     this.evaluatedTargets = new Dictionary <long, IDictionary <string, object> >();
 }
예제 #9
0
        internal static TelemetryEntry GetTelemetryEntry(this TargetDeliveryRequest request, TargetClientConfig config, int?execution = default)
        {
            if (!config.TelemetryEnabled)
            {
                return(null);
            }

            var decisioningMethod = request.DecisioningMethod != default(DecisioningMethod)
                ? request.DecisioningMethod : config.DecisioningMethod;

            return(new TelemetryEntry(
                       request.DeliveryRequest.RequestId,
                       DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                       execution,
                       new TelemetryFeatures(decisioningMethod)));
        }
        public Dictionary <string, object> CollateParams(TargetDeliveryRequest deliveryRequest = default, RequestDetails requestDetails = default)
        {
            var result = new Dictionary <string, object>();

            if (requestDetails?.Parameters == null || requestDetails.Parameters.Count == 0)
            {
                return(result);
            }

            foreach (var param in requestDetails.Parameters)
            {
                result.Add(param.Key, param.Value);
                result.Add(param.Key + LowerCasePostfix, param.Value?.ToLowerInvariant());
            }

            return(result);
        }
예제 #11
0
        /// <inheritdoc/>
        public Task <TargetDeliveryResponse> GetOffersAsync(TargetDeliveryRequest request)
        {
            Validators.ValidateClientInit(this.targetService);
            Validators.ValidateGetOffers(request);

            var decisioning = request.DecisioningMethod != default(DecisioningMethod) ? request.DecisioningMethod : this.defaultDecisioningMethod;

            this.UpdatePropertyToken(request);

            if (decisioning == DecisioningMethod.OnDevice ||
                (decisioning == DecisioningMethod.Hybrid && this.localService.EvaluateLocalExecution(request).AllLocal))
            {
                return(this.localService.ExecuteRequestAsync(request));
            }

            return(this.targetService.ExecuteRequestAsync(request));
        }
예제 #12
0
        private void UpdatePropertyToken(TargetDeliveryRequest request)
        {
            var property = request.DeliveryRequest.Property;

            if (string.IsNullOrEmpty(this.defaultPropertyToken) || property?.Token != null)
            {
                return;
            }

            if (property == null)
            {
                property = new Property(this.defaultPropertyToken);
                request.DeliveryRequest.Property = property;
                return;
            }

            property.Token = this.defaultPropertyToken;
        }
예제 #13
0
        public Dictionary <string, object> CollateParams(TargetDeliveryRequest deliveryRequest = default, RequestDetails requestDetails = default)
        {
            var result = new Dictionary <string, object>();
            var geo    = deliveryRequest?.DeliveryRequest?.Context?.Geo;

            if (geo == null)
            {
                result.AddAll(DefaultGeoParams);
                return(result);
            }

            result.Add(GeoLatitude, geo.Latitude);
            result.Add(GeoLongitude, geo.Longitude);
            result.Add(GeoCity, string.IsNullOrEmpty(geo.City) ? string.Empty : geo.City.Replace(" ", string.Empty).ToUpperInvariant());
            result.Add(GeoRegion, string.IsNullOrEmpty(geo.StateCode) ? string.Empty : geo.StateCode.ToUpperInvariant());
            result.Add(GeoCountry, string.IsNullOrEmpty(geo.CountryCode) ? string.Empty : geo.CountryCode.ToUpperInvariant());

            return(result);
        }
예제 #14
0
        public Dictionary <string, object> CollateParams(TargetDeliveryRequest deliveryRequest, RequestDetails requestDetails = default)
        {
            var result    = new Dictionary <string, object>();
            var userAgent = deliveryRequest.DeliveryRequest?.Context?.UserAgent;

            if (string.IsNullOrEmpty(userAgent))
            {
                result.Add(UserBrowserType, Unknown);
                result.Add(UserBrowserVersion, Unknown);
                result.Add(UserPlatform, Unknown);
                return(result);
            }

            var info = this.uaParser.Parse(userAgent);

            result.Add(UserBrowserType, GetBrowserType(info));
            result.Add(UserBrowserVersion, info.UA.Major == Parser.Other ? Unknown : info.UA.Major);
            result.Add(UserPlatform, GetPlatform(info));

            return(result);
        }
예제 #15
0
        public Dictionary <string, object> CollateParams(TargetDeliveryRequest deliveryRequest = default, RequestDetails requestDetails = default)
        {
            var result  = new Dictionary <string, object>();
            var address = requestDetails?.Address ?? deliveryRequest?.DeliveryRequest?.Context?.Address;
            var url     = this.referring ? address?.ReferringUrl : address?.Url;

            if (string.IsNullOrEmpty(url))
            {
                return(GetBlankPageParams(result));
            }

            try
            {
                var parsed     = new Uri(url);
                var domainInfo = this.GetDomainInfo(parsed.Host);
                var subdomain  = GetSubDomain(domainInfo.SubDomain);

                result.Add(PageUrl, parsed.OriginalString);
                result.Add(PageUrlLower, parsed.OriginalString.ToLowerInvariant());
                result.Add(PageDomain, parsed.Host);
                result.Add(PageDomainLower, parsed.Host.ToLowerInvariant());
                result.Add(PageSubdomain, subdomain);
                result.Add(PageSubdomainLower, subdomain.ToLowerInvariant());
                result.Add(PageTopLevelDomain, domainInfo.Tld);
                result.Add(PageTopLevelDomainLower, domainInfo.Tld.ToLowerInvariant());
                result.Add(PagePath, parsed.AbsolutePath);
                result.Add(PagePathLower, parsed.AbsolutePath.ToLowerInvariant());
                result.Add(PageQuery, parsed.Query);
                result.Add(PageQueryLower, parsed.Query.ToLowerInvariant());
                result.Add(PageFragment, parsed.Fragment);
                result.Add(PageFragmentLower, parsed.Fragment.ToLowerInvariant());
            }
            catch (UriFormatException)
            {
                this.logger?.LogWarning(Messages.MalformedAddressUrl + url);
            }

            return(result);
        }
예제 #16
0
        internal static void ValidateGetOffers(TargetDeliveryRequest deliveryRequest)
        {
            var request = deliveryRequest?.DeliveryRequest;

            if (request == null)
            {
                throw new ArgumentNullException(nameof(deliveryRequest));
            }

            if (request.Execute != null && request.Execute.PageLoad == null &&
                (request.Execute.Mboxes == null || request.Execute.Mboxes.Count == 0))
            {
                throw new ValidationException(Messages.ExecuteFieldsRequired);
            }

            if (request.Prefetch != null && request.Prefetch.PageLoad == null &&
                (request.Prefetch.Mboxes == null || request.Prefetch.Mboxes.Count == 0) &&
                (request.Prefetch.Views == null || request.Prefetch.Views.Count == 0))
            {
                throw new ValidationException(Messages.PrefetchFieldsRequired);
            }
        }
예제 #17
0
 internal static void LogRequest(this ILogger logger, TargetDeliveryRequest request)
 {
     logger?.LogDebug(Messages.LogTargetServiceRequest, request.SessionId, request.DeliveryRequest.ToJson());
 }
예제 #18
0
 private string GetLocationHint(TargetDeliveryRequest request)
 {
     return(request.LocationHint ?? this.stickyLocationHint);
 }
예제 #19
0
 private TargetDeliveryResponse GetTargetDeliveryResponse(TargetDeliveryRequest request, DeliveryResponse response)
 {
     this.UpdateStickyLocationHint(response);
     this.logger.LogResponse(response);
     return(new TargetDeliveryResponse(request, response, (HttpStatusCode)response.Status));
 }
예제 #20
0
        /// <inheritdoc />
        public async Task <TargetAttributes> GetAttributesAsync(TargetDeliveryRequest request, params string[] mboxes)
        {
            var response = await this.GetOffersAsync(AddMBoxesToRequest(request, mboxes));

            return(new TargetAttributes(response));
        }
예제 #21
0
        /// <inheritdoc />
        public TargetAttributes GetAttributes(TargetDeliveryRequest request, params string[] mboxes)
        {
            var response = this.GetOffers(AddMBoxesToRequest(request, mboxes));

            return(new TargetAttributes(response));
        }
예제 #22
0
 /// <inheritdoc />
 public Task <TargetDeliveryResponse> SendNotificationsAsync(TargetDeliveryRequest request)
 {
     Validators.ValidateClientInit(this.targetService);
     Validators.ValidateSendNotifications(request);
     return(this.targetService.ExecuteRequestAsync(request));
 }
        public void ExecuteDetails(
            TargetDeliveryRequest deliveryRequest,
            IDictionary <string, object> localContext,
            string visitorId,
            ISet <string> responseTokens,
            TraceHandler traceHandler,
            OnDeviceDecisioningRuleSet ruleSet,
            RequestDetailsUnion details,
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            IList <Notification> notifications)
        {
            traceHandler?.UpdateRequest(deliveryRequest, details, executeResponse != null);
            var rules = GetDetailsRules(details, ruleSet);

            if (rules == null)
            {
                UnhandledResponse(details, prefetchResponse, executeResponse, traceHandler);
                return;
            }

            var propertyToken      = deliveryRequest.DeliveryRequest.Property?.Token;
            var handledAtLeastOnce = false;
            var skipKeySet         = new HashSet <string>();

            foreach (var rule in rules)
            {
                if (PropertyTokenMismatch(rule.PropertyTokens, propertyToken))
                {
                    continue;
                }

                if (rule.RuleKey != null && skipKeySet.Contains(rule.RuleKey))
                {
                    continue;
                }

                var consequence = this.ruleExecutor.ExecuteRule(localContext, details, visitorId, rule, responseTokens, traceHandler);
                if (!HandleResult(consequence, rule, details, prefetchResponse, executeResponse, notifications, traceHandler, ruleSet.GlobalMbox))
                {
                    continue;
                }

                handledAtLeastOnce = true;
                if (rule.RuleKey != null)
                {
                    skipKeySet.Add(rule.RuleKey);
                }

                if (details.Match(
                        _ => false,
                        _ => true,
                        _ => false))
                {
                    break;
                }
            }

            if (!handledAtLeastOnce)
            {
                UnhandledResponse(details, prefetchResponse, executeResponse, traceHandler);
            }
        }