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); }
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())); } } }
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); }