Пример #1
0
        public static async Task <Leaderboard> GenerateDeltaLeaderboard(IGuild guild, DiscordBot bot, DateTimeOffset creationTime)
        {
            var leaderboard = new Leaderboard(guild.Id, LeaderboardType.Delta, bot, creationTime);

            if (bot.Leaderboards.Leaderboards.ContainsKey(guild.Id))
            {
                leaderboard.OldLeaderboard = bot.Leaderboards.Leaderboards[guild.Id];
            }
            else
            {
                return(await GenerateFullLeaderboard(guild, bot, creationTime));
            }

            leaderboard.ChannelMessages = leaderboard.OldLeaderboard.ChannelMessages.ToDictionary(x => x.Key, x => x.Value);
            leaderboard.UserMessages    = leaderboard.OldLeaderboard.UserMessages.ToDictionary(x => x.Key, x => x.Value);
            leaderboard.TotalMessages   = leaderboard.OldLeaderboard.TotalMessages;


            var channels = await guild.GetTextChannelsAsync();

            foreach (ITextChannel channel in channels)
            {
                ChannelPermissions permissions = (await guild.GetCurrentUserAsync()).GetPermissions(channel);
                if (!permissions.ViewChannel || !permissions.ReadMessageHistory)
                {
                    continue;
                }

                int messagesInChannel = 0;

                var      messages = (await channel.GetMessagesAsync(limit: 100).FlattenAsync()).ToList();
                IMessage lastMessage;
                do
                {
                    lastMessage = messages.LastOrDefault();

                    if (lastMessage == null)
                    {
                        break;
                    }

                    foreach (IMessage message in messages.Where(message => message.Timestamp > leaderboard.OldLeaderboard.TimeGenerated && message.Timestamp <= creationTime))
                    {
                        if (!leaderboard.UserMessages.ContainsKey(message.Author.Id))
                        {
                            leaderboard.UserMessages.Add(message.Author.Id, 0);
                        }
                        if (!leaderboard.UserLookup.ContainsKey(message.Author.Id))
                        {
                            leaderboard.UserLookup.Add(message.Author.Id, message.Author.NicknameOrUsername());
                        }

                        leaderboard.UserMessages[message.Author.Id]++;
                        messagesInChannel++;
                    }

                    messages = (await channel.GetMessagesAsync(lastMessage, Direction.Before).FlattenAsync()).ToList();
                } while (lastMessage.Timestamp > leaderboard.OldLeaderboard.TimeGenerated);

                if (!leaderboard.ChannelMessages.ContainsKey(channel.Id))
                {
                    leaderboard.ChannelMessages.Add(channel.Id, messagesInChannel);
                }
                else
                {
                    leaderboard.ChannelMessages[channel.Id] += messagesInChannel;
                }
                leaderboard.TotalMessages += messagesInChannel;
                if (!leaderboard.ChannelLookup.ContainsKey(channel.Id))
                {
                    leaderboard.ChannelLookup.Add(channel.Id, channel.Name);
                }
            }

            bot.Leaderboards.Leaderboards[guild.Id] = leaderboard;
            bot.Leaderboards.SaveConfig();

            return(leaderboard);
        }
Пример #2
0
        public static async Task <ICommandResult> GenerateLeaderboard(ICommandContext context, LeaderboardType type = LeaderboardType.Delta, [HelpText("Specifies the time frame for custom leaderboards")] double customHours = 24d)
        {
            IGuild         guild;
            ITextChannel   messageChannel;
            DateTimeOffset timestamp;

            switch (context)
            {
            case DiscordMessageContext d:
                guild          = d.Guild;
                messageChannel = (ITextChannel)d.Channel;
                timestamp      = d.Message.Timestamp;
                break;

            case DiscordChannelDescriptionContext d:
                guild          = d.Channel.Guild;
                messageChannel = (ITextChannel)d.Channel;
                timestamp      = DateTimeOffset.Now;
                break;

            default:
                return(new ErrorResult($"The `leaderboard` command is not valid in the context `{context.GetType().Name}`"));
            }

            IUserMessage leaderboardMessage = null;

            if (context is DiscordUserMessageContext)
            {
                leaderboardMessage = await messageChannel.SendMessageAsync("Calculating messages sent. This may take a few seconds...");

                await leaderboardMessage.AddReactionAsync(CommandTools.LoadingEmote);
            }

            using (messageChannel.EnterTypingState())
            {
                Leaderboard leaderboard;
                switch (type)
                {
                case LeaderboardType.Full:
                    leaderboard = await Leaderboard.GenerateFullLeaderboard(guild, context.Bot, timestamp);

                    break;

                case LeaderboardType.Today:
                case LeaderboardType.Past24Hours:
                    leaderboard = await Leaderboard.GenerateTimeBasedLeaderboard(guild, context.Bot, type, timestamp);

                    break;

                case LeaderboardType.Delta:
                    leaderboard = await Leaderboard.GenerateDeltaLeaderboard(guild, context.Bot, timestamp);

                    break;

                case LeaderboardType.Custom:
                    leaderboard = await Leaderboard.GenerateTimeBasedLeaderboard(guild, context.Bot, type, timestamp, customHours);

                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(type), type, null);
                }

                if (context is DiscordUserMessageContext)
                {
                    foreach (string message in await leaderboard.ToStringsAsync())
                    {
                        await context.Reply(message);
                    }

                    if (leaderboardMessage != null)
                    {
                        await leaderboardMessage.DeleteAsync();
                    }

                    return(new SuccessResult());
                }
                else
                {
                    return(new SuccessResult(await leaderboard.ToStringAsync()));
                }
            }
        }
Пример #3
0
        public static async Task <Leaderboard> GenerateTimeBasedLeaderboard(IGuild guild, DiscordBot bot, LeaderboardType type, DateTimeOffset creationTime, double hours = 24d)
        {
            var leaderboard = new Leaderboard(guild.Id, type, bot, creationTime, TimeSpan.FromHours(hours));

            Leaderboard    oldLeaderboard = new Leaderboard();
            DateTimeOffset startTime      = DateTimeOffset.MinValue;
            DateTimeOffset deltaTime      = DateTimeOffset.MinValue;

            if (type == LeaderboardType.Today)
            {
                // I'm sure this isn't the right way to do this but quite honestly I was getting annoyed and this works, so ¯\_(ツ)_/¯
                TimeSpan offset = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTimeOffset.UtcNow, bot.DefaultTimeZone).Offset;
                startTime = new DateTimeOffset(new DateTimeOffset(DateTime.UtcNow.Ticks + TimeSpan.FromHours(offset.Hours).Ticks, offset).Date, offset);
            }
            else if (type == LeaderboardType.Past24Hours)
            {
                startTime = DateTimeOffset.Now - TimeSpan.FromDays(1);
            }
            else if (type == LeaderboardType.Custom)
            {
                startTime = DateTimeOffset.Now - TimeSpan.FromHours(hours);
            }

            deltaTime      = startTime - TimeSpan.FromHours(hours);
            oldLeaderboard = new Leaderboard {
                TimeGenerated = deltaTime
            };
            leaderboard.OldLeaderboard = oldLeaderboard;

            var channels = await guild.GetTextChannelsAsync();

            foreach (ITextChannel channel in channels)
            {
                ChannelPermissions permissions = (await guild.GetCurrentUserAsync()).GetPermissions(channel);
                if (!permissions.ViewChannel || !permissions.ReadMessageHistory)
                {
                    continue;
                }

                int messagesInChannel = 0;
                oldLeaderboard.ChannelMessages[channel.Id] = 0;

                var      messages = (await channel.GetMessagesAsync(limit: 100).FlattenAsync()).ToList();
                IMessage lastMessage;
                do
                {
                    lastMessage = messages.LastOrDefault();

                    if (lastMessage == null)
                    {
                        break;
                    }

                    foreach (var message in messages)
                    {
                        if (message.Timestamp > startTime && message.Timestamp <= creationTime)
                        {
                            if (!leaderboard.UserMessages.ContainsKey(message.Author.Id))
                            {
                                leaderboard.UserMessages.Add(message.Author.Id, 0);
                                leaderboard.UserLookup.Add(message.Author.Id, message.Author.NicknameOrUsername());
                            }

                            leaderboard.UserMessages[message.Author.Id]++;
                            messagesInChannel++;
                        }
                        else if (message.Timestamp > deltaTime && message.Timestamp <= creationTime)
                        {
                            if (!oldLeaderboard.UserMessages.ContainsKey(message.Author.Id))
                            {
                                oldLeaderboard.UserMessages.Add(message.Author.Id, 0);
                                oldLeaderboard.UserLookup.Add(message.Author.Id, message.Author.NicknameOrUsername());
                            }

                            oldLeaderboard.UserMessages[message.Author.Id]++;
                            oldLeaderboard.ChannelMessages[channel.Id]++;
                            oldLeaderboard.TotalMessages++;
                        }
                    }

                    messages = (await channel.GetMessagesAsync(lastMessage, Direction.Before).FlattenAsync()).ToList();
                } while (lastMessage.Timestamp > deltaTime);

                leaderboard.ChannelMessages[channel.Id] = messagesInChannel;
                leaderboard.TotalMessages += messagesInChannel;
                leaderboard.ChannelLookup.Add(channel.Id, channel.Name);
            }
            return(leaderboard);
        }