public async Task ShowLeaderboard()
        {
            using (Context.Channel.EnterTypingState())
            {
                try
                {
                    _logger.LogInformation("Executing leaderboard command");
                    var start = DateTime.Now.AddDays(-7);
                    var groupedActivitiesByParticipant =
                        new Dictionary <LeaderboardParticipant, List <DetailedActivity> >();
                    var participants =
                        await _participantService.GetAllParticipantsForServerAsync(Context.Guild.Id.ToString());

                    foreach (var participant in participants)
                    {
                        try
                        {
                            groupedActivitiesByParticipant.Add(participant,
                                                               await _stravaService.FetchActivitiesForParticipant(participant,
                                                                                                                  start));
                        }
                        catch (StravaException e) when(e.Error == StravaException.StravaErrorType.RefreshFailed)
                        {
                            await AskToRelogin(participant.DiscordUserId);
                        }
                    }

                    var realRideCategoryResult = _leaderboardResultService.GetTopResultsForCategory(
                        groupedActivitiesByParticipant, Constants.LeaderboardRideType.RealRide,
                        x => x.Type == Constants.LeaderboardRideType.RealRide);
                    await ReplyAsync(embed : _embedBuilderService
                                     .BuildLeaderboardEmbed(
                                         realRideCategoryResult,
                                         start,
                                         DateTime.Now
                                         )
                                     );

                    var virtualRideCategoryResult = _leaderboardResultService.GetTopResultsForCategory(
                        groupedActivitiesByParticipant, Constants.LeaderboardRideType.VirtualRide,
                        x => x.Type == Constants.LeaderboardRideType.VirtualRide);
                    await ReplyAsync(embed : _embedBuilderService
                                     .BuildLeaderboardEmbed(
                                         virtualRideCategoryResult,
                                         start,
                                         DateTime.Now
                                         )
                                     );
                }
                catch (Exception e)
                {
                    _logger.LogError(e, "leaderboard failed");
                }
            }
        }
        public async Task GenerateForServer(IMessageChannel replyChannel, string serverId, DateTime start, bool grantWinnerRole, params ICategory[] categories)
        {
            _logger.LogInformation("Executing leaderboard command");
            if (grantWinnerRole)
            {
                await _roleService.RemoveRoleFromAllInServer(serverId, Constants.LeaderboardWinnerRoleName);
            }

            var participantsWithActivities = new List <ParticipantWithActivities>();
            var participants = _participantService.GetAllParticipantsForServerAsync(serverId);

            foreach (var participant in participants)
            {
                var(policy, context) = _stravaAuthenticationService.GetUnauthorizedPolicy(participant.StravaId);
                try
                {
                    var activities =
                        await policy.ExecuteAsync(x => _activitiesService.GetForStravaUser(participant.StravaId, start),
                                                  context);

                    participantsWithActivities.Add(new ParticipantWithActivities
                    {
                        Participant = participant,
                        Activities  = activities
                    });
                }
                catch (Exception e)
                {
                    _logger.LogWarning(e,
                                       $"Failed to fetch activities for {participant.DiscordUserId}, excluding participant from leaderboard");
                }
            }

            var categoryResults = new List <CategoryResult>();

            foreach (var category in categories)
            {
                var categoryResult = GetTopResultsForCategory(participantsWithActivities, category);
                await replyChannel.SendMessageAsync(embed : _embedBuilderService
                                                    .BuildLeaderboardEmbed(
                                                        categoryResult,
                                                        start,
                                                        DateTime.Now
                                                        )
                                                    );

                categoryResults.Add(categoryResult);
            }

            if (grantWinnerRole)
            {
                var winners = new List <ParticipantResult>();
                foreach (var subCategoryResult in categoryResults.SelectMany(categoryResult => categoryResult.SubCategoryResults))
                {
                    winners.AddRange(subCategoryResult.OrderedParticipantResults.Take(3));
                }

                await GrantWinnerRoles(serverId, winners);
            }
        }
        public async Task RemoveRoleFromAllParticipantsInServer(string serverId, string roleName)
        {
            var server = _discordSocketClient.GetGuild(ulong.Parse(serverId));
            var role   = server?.Roles.FirstOrDefault(x => x.Name == roleName);

            if (role == null)
            {
                _logger.LogWarning($"Role '{roleName}' not found in server '{serverId}'");
                return;
            }

            var participants = await _participantService.GetAllParticipantsForServerAsync(serverId);

            foreach (var participant in participants)
            {
                _logger.LogInformation($"Removing role from {participant?.DiscordUserId}");
                try
                {
                    var user = server.GetUser(ulong.Parse(participant?.DiscordUserId));
                    await user.RemoveRoleAsync(role);
                }
                catch (Exception e)
                {
                    _logger.LogError(e, $"Failed to remove role from {participant?.DiscordUserId} in server {serverId}");
                }
            }
        }
        public async Task RemoveRoleFromAllInServer(string serverId, string roleName)
        {
            var server = _discordSocketClient.GetGuild(serverId);

            if (!server.TryGetRole(roleName, out var role))
            {
                _logger.LogWarning($"Role '{roleName}' not found in server '{serverId}'");
                return;
            }

            var participants = _participantService.GetAllParticipantsForServerAsync(serverId);

            foreach (var participant in participants)
            {
                _logger.LogInformation($"Removing role from {participant?.DiscordUserId}");
                if (server.TryGetUser(participant?.DiscordUserId, out var user))
                {
                    await user.TryRemoveRoleAsync(role);
                }
                else
                {
                    _logger.LogError($"Failed ot find {participant?.DiscordUserId} user");
                }
            }
        }
Example #5
0
 public async Task UserCount()
 {
     using (Context.Channel.EnterTypingState())
     {
         try
         {
             var users = _participantService.GetAllParticipantsForServerAsync(Context.Guild.Id.ToString());
             await ReplyAsync($"Server has {users.Count} leaderboard participants");
         }
         catch (Exception e)
         {
             _logger.LogError(e, $"Failed to prune users");
             await ReplyAsync($"Failed - {e.Message}");
         }
     }
 }
Example #6
0
        public async Task ListLeaderboardParticipants()
        {
            using (Context.Channel.EnterTypingState())
            {
                try
                {
                    _logger.LogInformation("Executing list");
                    var embeds       = new List <Embed>();
                    var participants = _participantService.GetAllParticipantsForServerAsync(Context.Guild.Id.ToString());
                    foreach (var participant in participants)
                    {
                        var(policy, context) = _stravaAuthenticationService.GetUnauthorizedPolicy(participant.StravaId);
                        try
                        {
                            var athlete = await policy.ExecuteAsync(x => _athleteService.Get(participant.StravaId), context);

                            embeds.Add(_embedBuilderService.BuildAthleteInfoEmbed(participant, athlete));
                        }
                        catch (ApiException e)
                        {
                            _logger.LogWarning(e, $"Failed to fetch athlete info for {participant.DiscordUserId}");
                        }
                    }

                    if (!embeds.Any())
                    {
                        embeds.Add(
                            new EmbedBuilder()
                            .WithTitle("No participants found")
                            .WithCurrentTimestamp()
                            .Build()
                            );
                    }

                    foreach (var embed in embeds)
                    {
                        await ReplyAsync(embed : embed);
                    }
                }
                catch (Exception e)
                {
                    _logger.LogError(e, "list failed");
                }
            }
        }
        public override async Task DoWork(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Executing leaderboard hosted service");
            foreach (var leaderboard in await _leaderboardService.GetAllLeaderboards())
            {
                try
                {
                    _logger.LogInformation("Removing role from all users");
                    await _roleService.RemoveRoleFromAllParticipantsInServer(leaderboard.ServerId,
                                                                             Constants.LeaderboardWinnerRoleName);
                }
                catch (Exception e)
                {
                    _logger.LogError(e,
                                     $"Failed to remove leaderboard role from all users in '{leaderboard.ServerId}'");
                }

                var start = DateTime.Now.AddDays(-7);
                var groupedActivitiesByParticipant = new Dictionary <LeaderboardParticipant, List <DetailedActivity> >();
                var participants = await _participantService.GetAllParticipantsForServerAsync(leaderboard.ServerId);

                foreach (var participant in participants)
                {
                    try
                    {
                        groupedActivitiesByParticipant.Add(participant,
                                                           await _stravaService.FetchActivitiesForParticipant(participant, start));
                    }
                    catch (StravaException e) when(e.Error == StravaException.StravaErrorType.RefreshFailed)
                    {
                        await AskToRelogin(participant.DiscordUserId);
                    }
                }

                var channel = _discordSocketClient.GetChannel(ulong.Parse(leaderboard.ChannelId)) as SocketTextChannel;

                var realRideCategoryResult = _leaderboardResultService.GetTopResultsForCategory(
                    groupedActivitiesByParticipant, Constants.LeaderboardRideType.RealRide,
                    x => x.Type == Constants.LeaderboardRideType.RealRide);

                await channel.SendMessageAsync(embed : _embedBuilderService
                                               .BuildLeaderboardEmbed(realRideCategoryResult, start, DateTime.Now));

                var virtualRideCategoryResult = _leaderboardResultService.GetTopResultsForCategory(
                    groupedActivitiesByParticipant, Constants.LeaderboardRideType.VirtualRide,
                    x => x.Type == Constants.LeaderboardRideType.VirtualRide);

                await channel.SendMessageAsync(embed : _embedBuilderService
                                               .BuildLeaderboardEmbed(
                                                   virtualRideCategoryResult,
                                                   start,
                                                   DateTime.Now
                                                   )
                                               );

                var allParticipantResults =
                    realRideCategoryResult.ChallengeByChallengeResultDictionary.SelectMany(x => x.Value).Union(
                        virtualRideCategoryResult
                        .ChallengeByChallengeResultDictionary.SelectMany(x => x.Value));

                foreach (var participantResult in allParticipantResults)
                {
                    try
                    {
                        await _roleService.GrantUserRoleIfExists(leaderboard.ServerId,
                                                                 participantResult.Participant.DiscordUserId, Constants.LeaderboardWinnerRoleName);
                    }
                    catch (Exception e)
                    {
                        _logger.LogError(e,
                                         $"Failed to grant leaderboard role for '{participantResult.Participant.DiscordUserId}'");
                    }
                }
            }
        }