Пример #1
0
        /// <inheritdoc />
        public async Task RejectCampaignAsync(long campaignId)
        {
            AuthorizationService.RequireAuthenticatedUser();
            AuthorizationService.RequireClaims(AuthorizationClaim.PromotionsCloseCampaign);

            if (!(await PromotionCampaignRepository.TryCloseAsync(campaignId, AuthorizationService.CurrentUserId.Value, PromotionCampaignOutcome.Rejected)))
                throw new InvalidOperationException($"Campaign {campaignId} doesn't exist or is already closed");
        }
Пример #2
0
        /// <inheritdoc />
        public async Task AcceptCampaignAsync(long campaignId)
        {
            AuthorizationService.RequireAuthenticatedUser();
            AuthorizationService.RequireClaims(AuthorizationClaim.PromotionsCloseCampaign);

            using (var transaction = await PromotionCampaignRepository.BeginCloseTransactionAsync())
            {
                var campaign = await PromotionCampaignRepository.ReadDetailsAsync(campaignId);
                if (campaign is null)
                    throw new InvalidOperationException($"Campaign {campaignId} does not exist");

                if (!(campaign.CloseAction is null))
                    throw new InvalidOperationException($"Campaign {campaignId} is already closed");

                var timeSince = DateTime.UtcNow - campaign.CreateAction.Created;

                if (timeSince < TimeSpan.FromHours(48))
                    throw new InvalidOperationException($"Campaign {campaignId} cannot be accepted until 48 hours after its creation ({48 - timeSince.TotalHours:#.##} hrs remain)");

                try
                {
                    var subject = await UserService.GetGuildUserAsync(campaign.GuildId, campaign.Subject.Id);
                    if (subject.RoleIds.Contains(campaign.TargetRole.Id))
                        throw new InvalidOperationException($"User {campaign.Subject.DisplayName} is already a member of role {campaign.TargetRole.Name}");

                    var guild = await DiscordClient.GetGuildAsync(campaign.GuildId);
                    var targetRole = guild.GetRole(campaign.TargetRole.Id);
                    if (targetRole is null)
                        throw new InvalidOperationException($"Role {campaign.TargetRole.Name} no longer exists");

                    await subject.AddRoleAsync(targetRole);

                    foreach (var lowerRankRole in (await GetRankRolesAsync(AuthorizationService.CurrentGuildId.Value))
                        .TakeWhile(x => x.Id != targetRole.Id))
                    {
                        var lowerRole = guild.GetRole(lowerRankRole.Id);
                        if (!(lowerRole is null) && subject.RoleIds.Contains(lowerRole.Id))
                            await subject.RemoveRoleAsync(lowerRole);
                    }

                    await PromotionCampaignRepository.TryCloseAsync(campaignId, AuthorizationService.CurrentUserId.Value, PromotionCampaignOutcome.Accepted);
                }
                catch
                {
                    await PromotionCampaignRepository.TryCloseAsync(campaignId, AuthorizationService.CurrentUserId.Value, PromotionCampaignOutcome.Failed);
                    throw;
                }
                finally
                {
                    transaction.Commit();
                }
            }
        }
Пример #3
0
        /// <inheritdoc />
        public async Task AcceptCampaignAsync(long campaignId, bool force)
        {
            AuthorizationService.RequireAuthenticatedUser();
            AuthorizationService.RequireClaims(AuthorizationClaim.PromotionsCloseCampaign);

            PromotionActionSummary resultAction;

            using (var transaction = await PromotionCampaignRepository.BeginCloseTransactionAsync())
            {
                var campaign = await PromotionCampaignRepository.ReadDetailsAsync(campaignId);

                if (campaign is null)
                {
                    throw new InvalidOperationException($"Campaign {campaignId} does not exist");
                }

                if (!(campaign.CloseAction is null))
                {
                    throw new InvalidOperationException($"Campaign {campaignId} is already closed");
                }

                var timeSince = DateTime.UtcNow - campaign.CreateAction.Created;

                if (timeSince < PromotionCampaignEntityExtensions.CampaignAcceptCooldown && !force)
                {
                    throw new InvalidOperationException($"Campaign {campaignId} cannot be accepted until {PromotionCampaignEntityExtensions.CampaignAcceptCooldown.TotalHours} hours after its creation ({(PromotionCampaignEntityExtensions.CampaignAcceptCooldown - timeSince).Humanize(4)} remain)");
                }

                try
                {
                    var subject = await UserService.GetGuildUserAsync(campaign.GuildId, campaign.Subject.Id);

                    if (subject.RoleIds.Contains(campaign.TargetRole.Id))
                    {
                        throw new InvalidOperationException($"User {campaign.Subject.GetFullUsername()} is already a member of role {campaign.TargetRole.Name}");
                    }

                    var guild = await DiscordClient.GetGuildAsync(campaign.GuildId);

                    var targetRole = guild.GetRole(campaign.TargetRole.Id);
                    if (targetRole is null)
                    {
                        throw new InvalidOperationException($"Role {campaign.TargetRole.Name} no longer exists");
                    }

                    await subject.AddRoleAsync(targetRole);

                    foreach (var lowerRankRole in (await GetRankRolesAsync(AuthorizationService.CurrentGuildId.Value))
                             .TakeWhile(x => x.Id != targetRole.Id))
                    {
                        var lowerRole = guild.GetRole(lowerRankRole.Id);
                        if (!(lowerRole is null) && subject.RoleIds.Contains(lowerRole.Id))
                        {
                            await subject.RemoveRoleAsync(lowerRole);
                        }
                    }

                    resultAction = await PromotionCampaignRepository.TryCloseAsync(campaignId, AuthorizationService.CurrentUserId.Value, PromotionCampaignOutcome.Accepted);
                }
                catch
                {
                    resultAction = await PromotionCampaignRepository.TryCloseAsync(campaignId, AuthorizationService.CurrentUserId.Value, PromotionCampaignOutcome.Failed);

                    PublishActionNotificationAsync(resultAction);
                    throw;
                }
                finally
                {
                    transaction.Commit();
                }
            }

            PublishActionNotificationAsync(resultAction);
        }