.prune improved

This commit is contained in:
Master Kwoth 2017-06-17 00:17:07 +02:00
parent 8801a7451b
commit 277fbdbe4d
5 changed files with 145 additions and 65 deletions

View File

@ -9,7 +9,6 @@ using NadekoBot.Services;
using NadekoBot.Attributes;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Administration;
using Discord.WebSocket;
namespace NadekoBot.Modules.Administration
{
@ -311,67 +310,6 @@ namespace NadekoBot.Modules.Administration
await ReplyConfirmLocalized("set_channel_name").ConfigureAwait(false);
}
//delets her own messages, no perm required
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Prune()
{
var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
var enumerable = (await Context.Channel.GetMessagesAsync().Flatten())
.Where(x => x.Author.Id == user.Id && DateTime.UtcNow - x.CreatedAt < twoWeeks);
await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
Context.Message.DeleteAfter(3);
}
private TimeSpan twoWeeks => TimeSpan.FromDays(14);
// prune x
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(0)]
public async Task Prune(int count)
{
if (count < 1)
return;
await Context.Message.DeleteAsync().ConfigureAwait(false);
int limit = (count < 100) ? count + 1 : 100;
var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten().ConfigureAwait(false))
.Where(x => DateTime.UtcNow - x.CreatedAt < twoWeeks);
if (enumerable.FirstOrDefault()?.Id == Context.Message.Id)
enumerable = enumerable.Skip(1).ToArray();
else
enumerable = enumerable.Take(count);
await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
}
//prune @user [x]
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(1)]
public async Task Prune(IGuildUser user, int count = 100)
{
if (count < 1)
return;
if (count > 100)
count = 100;
if (user.Id == Context.User.Id)
count += 1;
var enumerable = (await Context.Channel.GetMessagesAsync().Flatten())
.Where(m => m.Author.Id == user.Id && DateTime.UtcNow - m.CreatedAt < twoWeeks)
.Take(count);
await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
Context.Message.DeleteAfter(3);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.MentionEveryone)]

View File

@ -0,0 +1,70 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services.Administration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class PruneCommands : ModuleBase
{
private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
private readonly PruneService _prune;
public PruneCommands(PruneService prune)
{
_prune = prune;
}
//delets her own messages, no perm required
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Prune()
{
var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
await _prune.PruneWhere((ITextChannel)Context.Channel, 100, (x) => x.Author.Id == user.Id).ConfigureAwait(false);
Context.Message.DeleteAfter(3);
}
// prune x
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(0)]
public async Task Prune(int count)
{
if (count < 1)
return;
if (count > 1000)
count = 1000;
await Context.Message.DeleteAsync().ConfigureAwait(false);
await _prune.PruneWhere((ITextChannel)Context.Channel, count, x => true).ConfigureAwait(false);
}
//prune @user [x]
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(ChannelPermission.ManageMessages)]
[RequireBotPermission(GuildPermission.ManageMessages)]
[Priority(1)]
public async Task Prune(IGuildUser user, int count = 100)
{
if (count < 1)
return;
if (count > 1000)
count = 1000;
await _prune.PruneWhere((ITextChannel)Context.Channel, count, m => m.Author.Id == user.Id && DateTime.UtcNow - m.CreatedAt < twoWeeks);
}
}
}
}

View File

@ -121,8 +121,10 @@ namespace NadekoBot.Modules
return Task.CompletedTask;
}
userInputTask.SetResult(arg.Content);
userMsg.DeleteAfter(1);
if (userInputTask.TrySetResult(arg.Content))
{
userMsg.DeleteAfter(1);
}
return Task.CompletedTask;
});
return Task.CompletedTask;

View File

@ -92,7 +92,7 @@ namespace NadekoBot
CommandService = new CommandService(new CommandServiceConfig()
{
CaseSensitiveCommands = false,
DefaultRunMode = RunMode.Sync,
DefaultRunMode = RunMode.Async,
});
//foundation services
@ -127,6 +127,7 @@ namespace NadekoBot
var commandMapService = new CommandMapService(AllGuildConfigs);
var patreonRewardsService = new PatreonRewardsService(Credentials, Db, Currency);
var verboseErrorsService = new VerboseErrorsService(AllGuildConfigs, Db, CommandHandler, helpService);
var pruneService = new PruneService();
#endregion
#region permissions
@ -197,6 +198,7 @@ namespace NadekoBot
.Add(converterService)
.Add(verboseErrorsService)
.Add(patreonRewardsService)
.Add(pruneService)
.Add<SearchesService>(searchesService)
.Add(streamNotificationService)
.Add(animeSearchService)

View File

@ -0,0 +1,68 @@
using Discord;
using NadekoBot.Extensions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Administration
{
public class PruneService
{
//channelids where prunes are currently occuring
private ConcurrentHashSet<ulong> _pruningChannels = new ConcurrentHashSet<ulong>();
private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
public async Task PruneWhere(ITextChannel channel, int amount, Func<IMessage, bool> predicate)
{
channel.ThrowIfNull(nameof(channel));
if (amount <= 0)
throw new ArgumentOutOfRangeException(nameof(amount));
if (!_pruningChannels.Add(channel.Id))
return;
try
{
IMessage[] msgs;
IMessage lastMessage = null;
msgs = (await channel.GetMessagesAsync(amount > 100 ? 100 : amount).Flatten()).Where(predicate).ToArray();
while (amount > 0 && msgs.Any())
{
lastMessage = msgs[msgs.Length - 1];
var bulkDeletable = new List<IMessage>();
var singleDeletable = new List<IMessage>();
foreach (var x in msgs)
{
if (DateTime.UtcNow - x.CreatedAt < twoWeeks)
bulkDeletable.Add(x);
else
singleDeletable.Add(x);
}
if (bulkDeletable.Count > 0)
await Task.WhenAll(Task.Delay(1000), channel.DeleteMessagesAsync(bulkDeletable)).ConfigureAwait(false);
var i = 0;
foreach (var group in singleDeletable.GroupBy(x => ++i / (singleDeletable.Count / 5)))
await Task.WhenAll(Task.Delay(1000), Task.WhenAll(group.Select(x => x.DeleteAsync()))).ConfigureAwait(false);
amount -= 100;
if(amount > 0)
msgs = (await channel.GetMessagesAsync(lastMessage, Direction.Before, amount > 100 ? 100 : amount).Flatten()).Where(predicate).ToArray();
}
}
catch (Exception ex)
{
}
finally
{
_pruningChannels.TryRemove(channel.Id);
}
}
}
}