Restructured the project structure back to the way it was, there's no reasonable way to split the modules

This commit is contained in:
Kwoth
2024-04-26 22:26:24 +00:00
parent 6c9c8bf63e
commit e0819f760c
768 changed files with 192 additions and 1047 deletions

View File

@@ -0,0 +1,114 @@
#nullable disable
using CommandLine;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Modules.Administration;
public partial class Administration
{
[Group]
public partial class PruneCommands : NadekoModule<PruneService>
{
private static readonly TimeSpan _twoWeeks = TimeSpan.FromDays(14);
public sealed class PruneOptions : INadekoCommandOptions
{
[Option(shortName: 's', longName: "safe", Default = false, HelpText = "Whether pinned messages should be deleted.", Required = false)]
public bool Safe { get; set; }
[Option(shortName: 'a', longName: "after", Default = null, HelpText = "Prune only messages after the specified message ID.", Required = false)]
public ulong? After { get; set; }
public void NormalizeOptions()
{
}
}
//deletes her own messages, no perm required
[Cmd]
[RequireContext(ContextType.Guild)]
[NadekoOptions<PruneOptions>]
public async Task Prune(params string[] args)
{
var (opts, _) = OptionsParser.ParseFrom(new PruneOptions(), args);
var user = await ctx.Guild.GetCurrentUserAsync();
if (opts.Safe)
await _service.PruneWhere((ITextChannel)ctx.Channel, 100, x => x.Author.Id == user.Id && !x.IsPinned, opts.After);
else
await _service.PruneWhere((ITextChannel)ctx.Channel, 100, x => x.Author.Id == user.Id, opts.After);
ctx.Message.DeleteAfter(3);
}
// prune x
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(ChannelPerm.ManageMessages)]
[BotPerm(ChannelPerm.ManageMessages)]
[NadekoOptions<PruneOptions>]
[Priority(1)]
public async Task Prune(int count, params string[] args)
{
count++;
if (count < 1)
return;
if (count > 1000)
count = 1000;
var (opts, _) = OptionsParser.ParseFrom<PruneOptions>(new PruneOptions(), args);
if (opts.Safe)
await _service.PruneWhere((ITextChannel)ctx.Channel, count, x => !x.IsPinned, opts.After);
else
await _service.PruneWhere((ITextChannel)ctx.Channel, count, _ => true, opts.After);
}
//prune @user [x]
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(ChannelPerm.ManageMessages)]
[BotPerm(ChannelPerm.ManageMessages)]
[NadekoOptions<PruneOptions>]
[Priority(0)]
public Task Prune(IGuildUser user, int count = 100, params string[] args)
=> Prune(user.Id, count, args);
//prune userid [x]
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(ChannelPerm.ManageMessages)]
[BotPerm(ChannelPerm.ManageMessages)]
[NadekoOptions<PruneOptions>]
[Priority(0)]
public async Task Prune(ulong userId, int count = 100, params string[] args)
{
if (userId == ctx.User.Id)
count++;
if (count < 1)
return;
if (count > 1000)
count = 1000;
var (opts, _) = OptionsParser.ParseFrom<PruneOptions>(new PruneOptions(), args);
if (opts.Safe)
{
await _service.PruneWhere((ITextChannel)ctx.Channel,
count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned,
opts.After);
}
else
{
await _service.PruneWhere((ITextChannel)ctx.Channel,
count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks,
opts.After);
}
}
}
}

View File

@@ -0,0 +1,89 @@
#nullable disable
namespace NadekoBot.Modules.Administration.Services;
public class PruneService : INService
{
//channelids where prunes are currently occuring
private readonly ConcurrentHashSet<ulong> _pruningGuilds = new();
private readonly TimeSpan _twoWeeks = TimeSpan.FromDays(14);
private readonly ILogCommandService _logService;
public PruneService(ILogCommandService logService)
=> _logService = logService;
public async Task PruneWhere(ITextChannel channel, int amount, Func<IMessage, bool> predicate, ulong? after = null)
{
ArgumentNullException.ThrowIfNull(channel, nameof(channel));
if (amount <= 0)
throw new ArgumentOutOfRangeException(nameof(amount));
if (!_pruningGuilds.Add(channel.GuildId))
return;
try
{
var now = DateTime.UtcNow;
IMessage[] msgs;
IMessage lastMessage = null;
var dled = await channel.GetMessagesAsync(50).FlattenAsync();
msgs = dled
.Where(predicate)
.Where(x => after is ulong a ? x.Id > a : true)
.Take(amount)
.ToArray();
while (amount > 0 && msgs.Any())
{
lastMessage = msgs[^1];
var bulkDeletable = new List<IMessage>();
var singleDeletable = new List<IMessage>();
foreach (var x in msgs)
{
_logService.AddDeleteIgnore(x.Id);
if (now - x.CreatedAt < _twoWeeks)
bulkDeletable.Add(x);
else
singleDeletable.Add(x);
}
if (bulkDeletable.Count > 0)
{
await channel.DeleteMessagesAsync(bulkDeletable);
await Task.Delay(2000);
}
foreach (var group in singleDeletable.Chunk(5))
{
await group.Select(x => x.DeleteAsync()).WhenAll();
await Task.Delay(5000);
}
//this isn't good, because this still work as if i want to remove only specific user's messages from the last
//100 messages, Maybe this needs to be reduced by msgs.Length instead of 100
amount -= 50;
if (amount > 0)
{
dled = await channel.GetMessagesAsync(lastMessage, Direction.Before, 50).FlattenAsync();
msgs = dled
.Where(predicate)
.Where(x => after is ulong a ? x.Id > a : true)
.Take(amount)
.ToArray();
}
}
}
catch
{
//ignore
}
finally
{
_pruningGuilds.TryRemove(channel.GuildId);
}
}
}