private async Task DoRescindInfractionAsync(InfractionSummary infraction) { if (infraction == null) { throw new InvalidOperationException("Infraction does not exist"); } await InfractionRepository.TryRescindAsync(infraction.Id, AuthorizationService.CurrentUserId.Value); var guild = await GuildService.GetGuildAsync(infraction.GuildId); var subject = await UserService.GetGuildUserAsync(guild.Id, infraction.Subject.Id); switch (infraction.Type) { case InfractionType.Mute: await subject.RemoveRoleAsync( await GetOrCreateMuteRoleInGuildAsync(guild)); break; case InfractionType.Ban: await guild.RemoveBanAsync(subject); break; default: throw new InvalidOperationException($"{infraction.Type} infractions cannot be rescinded."); } }
/// <inheritdoc /> public async Task DeleteInfractionAsync(long infractionId) { AuthorizationService.RequireAuthenticatedUser(); AuthorizationService.RequireClaims(AuthorizationClaim.ModerationDelete); var infraction = await InfractionRepository.ReadSummaryAsync(infractionId); if (infraction == null) { throw new InvalidOperationException($"Infraction {infractionId} does not exist"); } await InfractionRepository.TryDeleteAsync(infraction.Id, AuthorizationService.CurrentUserId.Value); var guild = await GuildService.GetGuildAsync(infraction.GuildId); var subject = await UserService.GetGuildUserAsync(guild.Id, infraction.Subject.Id); switch (infraction.Type) { case InfractionType.Mute: await subject.RemoveRoleAsync( await GetOrCreateMuteRoleInGuildAsync(guild)); break; case InfractionType.Ban: await guild.RemoveBanAsync(subject); break; } }
private async Task DoDiscordUnBanAsync(ulong subjectId) { AuthorizationService.RequireAuthenticatedGuild(); AuthorizationService.RequireAuthenticatedUser(); var guild = await GuildService.GetGuildAsync(AuthorizationService.CurrentGuildId.Value); var subject = await UserService.GetGuildUserAsync(guild.Id, subjectId); if (!(await guild.GetBansAsync()).Any(x => x.User.Id == subject.Id)) { throw new InvalidOperationException($"Discord user {subjectId} is not currently banned"); } await guild.AddBanAsync(subject); }
private async Task DoDiscordUnMuteAsync(ulong subjectId) { AuthorizationService.RequireAuthenticatedGuild(); AuthorizationService.RequireAuthenticatedUser(); var guild = await GuildService.GetGuildAsync(AuthorizationService.CurrentGuildId.Value); var muteRole = await GetOrCreateMuteRoleAsync(guild); var subject = await UserService.GetGuildUserAsync(guild.Id, subjectId); if (!subject.RoleIds.Contains(muteRole.Id)) { throw new InvalidOperationException($"Discord user {subjectId} is not currently muted"); } await subject.AddRoleAsync(muteRole); }
/// <inheritdoc /> public async Task CreateInfractionAsync(InfractionType type, ulong subjectId, string reason, TimeSpan?duration) { AuthorizationService.RequireAuthenticatedGuild(); AuthorizationService.RequireAuthenticatedUser(); AuthorizationService.RequireClaims(_createInfractionClaimsByType[type]); var guild = await GuildService.GetGuildAsync(AuthorizationService.CurrentGuildId.Value); var subject = await UserService.GetGuildUserAsync(guild.Id, subjectId); if (reason == null) { throw new ArgumentNullException(nameof(reason)); } if (((type == InfractionType.Notice) || (type == InfractionType.Warning)) && string.IsNullOrWhiteSpace(reason)) { throw new InvalidOperationException($"{type.ToString()} infractions require a reason to be given"); } using (var transaction = await InfractionRepository.BeginCreateTransactionAsync()) { if ((type == InfractionType.Mute) || (type == InfractionType.Ban)) { if (await InfractionRepository.AnyAsync(new InfractionSearchCriteria() { GuildId = guild.Id, Types = new[] { type }, SubjectId = subject.Id, IsRescinded = false, IsDeleted = false })) { throw new InvalidOperationException($"Discord user {subjectId} already has an active {type} infraction"); } } await InfractionRepository.CreateAsync( new InfractionCreationData() { GuildId = guild.Id, Type = type, SubjectId = subjectId, Reason = reason, Duration = duration, CreatedById = AuthorizationService.CurrentUserId.Value }); transaction.Commit(); } // TODO: Implement ModerationSyncBehavior to listen for mutes and bans that happen directly in Discord, instead of through bot commands, // and to read the Discord Audit Log to check for mutes and bans that were missed during downtime, and add all such actions to // the Infractions and ModerationActions repositories. // Note that we'll need to upgrade to the latest Discord.NET version to get access to the audit log. // Assuming that our Infractions repository is always correct, regarding the state of the Discord API. switch (type) { case InfractionType.Mute: await subject.AddRoleAsync( await GetOrCreateMuteRoleInGuildAsync(guild)); break; case InfractionType.Ban: await guild.AddBanAsync(subject, reason : reason); break; } }