private async Task<ShareIntent> TriggerCampaignIntentAsync(int id, string user, string medium)
        {
            var campaign = context.Campaigns.Include("OnShareIntentTriggers").FirstOrDefault(x => x.ID == id);
            if (campaign == null)
                throw new ArgumentException("No campaign was found with an ID: " + id);

            //Run all triggers
            var tasks = new List<Task>();
            foreach(var triggerIntent in campaign.OnShareIntentTriggers)
            {
                if (triggerIntent.IsOneTimeOnly && context.TriggerClaims.Any(tc => tc.TriggerID == triggerIntent.ID && tc.UserHandle == user))
                    continue;

                tasks.Add(triggerIntent.Execute(user));
                context.TriggerClaims.Add(new TriggerClaim() { UserHandle = user, Trigger = triggerIntent, Campaign = campaign });
            }
            await Task.WhenAll(tasks);

            var intent = new ShareIntent() { 
                SeedUserHandle = user, 
                Timestamp = DateTimeOffset.Now, 
                ViralMedium = medium, 
                Campaign = campaign 
            };

            context.ShareIntents.Add(intent);
            context.SaveChanges();

            return intent;
        }
        private async Task<ShareIntent> TriggerCampaignCallbackAsync(ShareIntent intent, string user, bool isConversion)
        {
            //Run all triggers
            var tasks = new List<Task>();

            var triggers = isConversion ? intent.Campaign.OnShareConversionTriggers : intent.Campaign.OnShareCallbackTriggers;

            foreach (var callback in triggers)
            {
                if (callback.IsOneTimeOnly && context.TriggerClaims.Any(tc => tc.TriggerID == callback.ID && tc.UserHandle == user))
                    continue;

                tasks.Add(callback.Execute(user, intent.SeedUserHandle));
                context.TriggerClaims.Add(new TriggerClaim() { UserHandle = user, Trigger = callback, Campaign = intent.Campaign });
            }

            await Task.WhenAll(tasks);

            var shareCallback = new ShareCallback()
            {
                CallbackUserHandle = user,
                Campaign = intent.Campaign,
                IsConversion = isConversion, //TODO: Check if it is conversion
                ReferalUserHandle = intent.SeedUserHandle,
                ShareIntent = intent,
                Timestamp = DateTimeOffset.Now
            };

            context.ShareCallbacks.Add(shareCallback);
            await context.SaveChangesAsync();

            return intent;
        }
        private async Task<string> ShortenUrl(string url, ShareIntent shareIntent) 
        {
            IUrlShortener service = new WmlUrlShortener();
            shareIntent.ShortenedUrl = await service.ShortenUrlAsync(url, "", NumericCompressionAlgorithm.Compress(shareIntent.ID));
            shareIntent.TargetUrl = url;
            context.SaveChanges();

            LogExtensions.Log.DebugCall(() => new { url, shareIntent.ShortenedUrl });

            return shareIntent.ShortenedUrl;
        }