Remove EnforceBlockingAttribute and all related logic

Users have been instructed to manually set command permissions from now on
This commit is contained in:
Noi 2023-01-16 21:43:07 -08:00
parent 61126eb84e
commit e4f5c90aab
9 changed files with 170 additions and 163 deletions

View file

@ -9,7 +9,6 @@ namespace BirthdayBot.ApplicationCommands;
/// <summary> /// <summary>
/// Base class for our interaction module classes. Contains common data for use in implementing classes. /// Base class for our interaction module classes. Contains common data for use in implementing classes.
/// </summary> /// </summary>
[EnforceBlocking]
public abstract class BotModuleBase : InteractionModuleBase<SocketInteractionContext> { public abstract class BotModuleBase : InteractionModuleBase<SocketInteractionContext> {
protected const string HelpPfxModOnly = "Bot moderators only: "; protected const string HelpPfxModOnly = "Bot moderators only: ";
protected const string ErrGuildOnly = ":x: This command can only be run within a server."; protected const string ErrGuildOnly = ":x: This command can only be run within a server.";

View file

@ -142,63 +142,6 @@ public class ConfigModule : BotModuleBase {
} }
} }
public const string ObsoleteAttrReason = "Made redundant by Discord's built-in command permissions. Will be removed eventually.";
const string ObsoleteNotice = ":x: This feature has been deprecated, and the setting of blocks has been disabled. "
+ "All existing blocks that have been previously set up will cease to function in the near future.\n"
+ "Please use Discord's equivalent built-in features to limit access to your users. "
+ "For more information: https://discord.com/blog/slash-commands-permissions-discord-apps-bots.";
[Obsolete(ObsoleteAttrReason)]
[Group("block", HelpCmdBlocking)]
public class SubCmdsConfigBlocking : BotModuleBase {
[SlashCommand("add-block", HelpPfxModOnly + "Add a user to the block list.")]
public Task CmdAddBlock([Summary(description: "The user to block.")] SocketGuildUser user) => UpdateBlockAsync(user, true);
[SlashCommand("remove-block", HelpPfxModOnly + "Remove a user from the block list.")]
public Task CmdDelBlock([Summary(description: "The user to unblock.")] SocketGuildUser user) => UpdateBlockAsync(user, false);
private async Task UpdateBlockAsync(SocketGuildUser user, bool setting) {
// setting: true to add (set), false to remove (unset)
using var db = new BotDatabaseContext();
var existing = db.BlocklistEntries
.Where(bl => bl.GuildId == user.Guild.Id && bl.UserId == user.Id).FirstOrDefault();
var already = (existing != null) == setting;
if (already) {
await RespondAsync($":white_check_mark: User is already {(setting ? "" : "not ")}blocked.").ConfigureAwait(false);
return;
}
if (setting) {
await RespondAsync(ObsoleteNotice);
return;
} else db.Remove(existing!);
await db.SaveChangesAsync();
await RespondAsync($":white_check_mark: {Common.FormatName(user, false)} has been {(setting ? "" : "un")}blocked.");
}
[SlashCommand("set-moderated", HelpPfxModOnly + "Set moderated mode on the server.")]
public async Task CmdSetModerated([Summary(name: "enable", description: "The moderated mode setting.")] bool setting) {
if (setting == true) {
await RespondAsync(ObsoleteNotice);
return;
}
var current = false;
await DoDatabaseUpdate(Context, s => {
current = s.Moderated;
s.Moderated = setting;
});
var already = setting == current;
if (already) {
await RespondAsync($":white_check_mark: Moderated mode is already **{(setting ? "en" : "dis")}abled**.");
} else {
await RespondAsync($":white_check_mark: Moderated mode is now **{(setting ? "en" : "dis")}abled**.").ConfigureAwait(false);
}
}
}
[SlashCommand("check", HelpPfxModOnly + HelpCmdCheck)] [SlashCommand("check", HelpPfxModOnly + HelpCmdCheck)]
public async Task CmdCheck() { public async Task CmdCheck() {
static string DoTestFor(string label, Func<bool> test) => $"{label}: { (test() ? ":white_check_mark: Yes" : ":x: No") }"; static string DoTestFor(string label, Func<bool> test) => $"{label}: { (test() ? ":white_check_mark: Yes" : ":x: No") }";

View file

@ -1,43 +0,0 @@
using BirthdayBot.Data;
using Discord.Interactions;
namespace BirthdayBot.ApplicationCommands;
/// <summary>
/// Only users not on the blocklist or affected by moderator mode may use the command.<br/>
/// This is used in the <see cref="BotModuleBase"/> base class. Manually using it anywhere else is unnecessary.
/// </summary>
[Obsolete(ConfigModule.ObsoleteAttrReason)]
class EnforceBlockingAttribute : PreconditionAttribute {
public const string FailModerated = "Guild has moderator mode enabled.";
public const string FailBlocked = "User is in the guild's block list.";
public const string ReplyModerated = ":x: This bot is in moderated mode, preventing you from using any bot commands in this server.";
public const string ReplyBlocked = ":x: You have been blocked from using bot commands in this server.";
public override Task<PreconditionResult> CheckRequirementsAsync(
IInteractionContext context, ICommandInfo commandInfo, IServiceProvider services) {
// Not in guild context, unaffected by blocking
if (context.Guild is not SocketGuild guild) return Task.FromResult(PreconditionResult.FromSuccess());
// Manage Guild permission overrides any blocks
var user = (SocketGuildUser)context.User;
if (user.GuildPermissions.ManageGuild) return Task.FromResult(PreconditionResult.FromSuccess());
using var db = new BotDatabaseContext();
var settings = (from row in db.GuildConfigurations
where row.GuildId == guild.Id
select new { ModRole = row.ModeratorRole, ModMode = row.Moderated }).FirstOrDefault();
if (settings != null) {
// Bot moderators override all blocking measures in place
if (user.Roles.Any(r => r.Id == settings.ModRole)) return Task.FromResult(PreconditionResult.FromSuccess());
// Check for moderated mode
if (settings.ModMode) return Task.FromResult(PreconditionResult.FromError(FailModerated));
// Check if user exists in blocklist
if (db.BlocklistEntries.Where(row => row.GuildId == guild.Id && row.UserId == user.Id).Any())
return Task.FromResult(PreconditionResult.FromError(FailBlocked));
}
return Task.FromResult(PreconditionResult.FromSuccess());
}
}

View file

@ -1,17 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BirthdayBot.Data;
[Obsolete(ApplicationCommands.ConfigModule.ObsoleteAttrReason)]
[Table("banned_users")]
public class BlocklistEntry {
[Key]
public ulong GuildId { get; set; }
[Key]
public ulong UserId { get; set; }
[ForeignKey(nameof(GuildConfig.GuildId))]
[InverseProperty(nameof(GuildConfig.BlockedUsers))]
public GuildConfig Guild { get; set; } = null!;
}

View file

@ -17,8 +17,6 @@ public class BotDatabaseContext : DbContext {
}.ToString(); }.ToString();
} }
[Obsolete(ApplicationCommands.ConfigModule.ObsoleteAttrReason)]
public DbSet<BlocklistEntry> BlocklistEntries { get; set; } = null!;
public DbSet<GuildConfig> GuildConfigurations { get; set; } = null!; public DbSet<GuildConfig> GuildConfigurations { get; set; } = null!;
public DbSet<UserEntry> UserEntries { get; set; } = null!; public DbSet<UserEntry> UserEntries { get; set; } = null!;
@ -28,17 +26,6 @@ public class BotDatabaseContext : DbContext {
.UseSnakeCaseNamingConvention(); .UseSnakeCaseNamingConvention();
protected override void OnModelCreating(ModelBuilder modelBuilder) { protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity<BlocklistEntry>(entity => {
entity.HasKey(e => new { e.GuildId, e.UserId })
.HasName("banned_users_pkey");
entity.HasOne(d => d.Guild)
.WithMany(p => p.BlockedUsers)
.HasForeignKey(d => d.GuildId)
.HasConstraintName("banned_users_guild_id_fkey")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<GuildConfig>(entity => { modelBuilder.Entity<GuildConfig>(entity => {
entity.HasKey(e => e.GuildId) entity.HasKey(e => e.GuildId)
.HasName("settings_pkey"); .HasName("settings_pkey");

View file

@ -0,0 +1,131 @@
// <auto-generated />
using System;
using BirthdayBot.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace BirthdayBot.Data.Migrations
{
[DbContext(typeof(BotDatabaseContext))]
[Migration("20230117053251_RemoveBlocking")]
partial class RemoveBlocking
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("BirthdayBot.Data.GuildConfig", b =>
{
b.Property<decimal>("GuildId")
.HasColumnType("numeric(20,0)")
.HasColumnName("guild_id");
b.Property<string>("AnnounceMessage")
.HasColumnType("text")
.HasColumnName("announce_message");
b.Property<string>("AnnounceMessagePl")
.HasColumnType("text")
.HasColumnName("announce_message_pl");
b.Property<bool>("AnnouncePing")
.HasColumnType("boolean")
.HasColumnName("announce_ping");
b.Property<decimal?>("AnnouncementChannel")
.HasColumnType("numeric(20,0)")
.HasColumnName("channel_announce_id");
b.Property<decimal?>("BirthdayRole")
.HasColumnType("numeric(20,0)")
.HasColumnName("role_id");
b.Property<string>("GuildTimeZone")
.HasColumnType("text")
.HasColumnName("time_zone");
b.Property<DateTimeOffset>("LastSeen")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("last_seen")
.HasDefaultValueSql("now()");
b.Property<bool>("Moderated")
.HasColumnType("boolean")
.HasColumnName("moderated");
b.Property<decimal?>("ModeratorRole")
.HasColumnType("numeric(20,0)")
.HasColumnName("moderator_role");
b.HasKey("GuildId")
.HasName("settings_pkey");
b.ToTable("settings", (string)null);
});
modelBuilder.Entity("BirthdayBot.Data.UserEntry", b =>
{
b.Property<decimal>("GuildId")
.HasColumnType("numeric(20,0)")
.HasColumnName("guild_id");
b.Property<decimal>("UserId")
.HasColumnType("numeric(20,0)")
.HasColumnName("user_id");
b.Property<int>("BirthDay")
.HasColumnType("integer")
.HasColumnName("birth_day");
b.Property<int>("BirthMonth")
.HasColumnType("integer")
.HasColumnName("birth_month");
b.Property<DateTimeOffset>("LastSeen")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("last_seen")
.HasDefaultValueSql("now()");
b.Property<string>("TimeZone")
.HasColumnType("text")
.HasColumnName("time_zone");
b.HasKey("GuildId", "UserId")
.HasName("user_birthdays_pkey");
b.ToTable("user_birthdays", (string)null);
});
modelBuilder.Entity("BirthdayBot.Data.UserEntry", b =>
{
b.HasOne("BirthdayBot.Data.GuildConfig", "Guild")
.WithMany("UserEntries")
.HasForeignKey("GuildId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("user_birthdays_guild_id_fkey");
b.Navigation("Guild");
});
modelBuilder.Entity("BirthdayBot.Data.GuildConfig", b =>
{
b.Navigation("UserEntries");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BirthdayBot.Data.Migrations
{
/// <inheritdoc />
public partial class RemoveBlocking : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "banned_users");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "banned_users",
columns: table => new
{
guildid = table.Column<decimal>(name: "guild_id", type: "numeric(20,0)", nullable: false),
userid = table.Column<decimal>(name: "user_id", type: "numeric(20,0)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("banned_users_pkey", x => new { x.guildid, x.userid });
table.ForeignKey(
name: "banned_users_guild_id_fkey",
column: x => x.guildid,
principalTable: "settings",
principalColumn: "guild_id",
onDelete: ReferentialAction.Cascade);
});
}
}
}

View file

@ -22,22 +22,6 @@ namespace BirthdayBot.Data.Migrations
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("BirthdayBot.Data.BlocklistEntry", b =>
{
b.Property<decimal>("GuildId")
.HasColumnType("numeric(20,0)")
.HasColumnName("guild_id");
b.Property<decimal>("UserId")
.HasColumnType("numeric(20,0)")
.HasColumnName("user_id");
b.HasKey("GuildId", "UserId")
.HasName("banned_users_pkey");
b.ToTable("banned_users", (string)null);
});
modelBuilder.Entity("BirthdayBot.Data.GuildConfig", b => modelBuilder.Entity("BirthdayBot.Data.GuildConfig", b =>
{ {
b.Property<decimal>("GuildId") b.Property<decimal>("GuildId")
@ -122,18 +106,6 @@ namespace BirthdayBot.Data.Migrations
b.ToTable("user_birthdays", (string)null); b.ToTable("user_birthdays", (string)null);
}); });
modelBuilder.Entity("BirthdayBot.Data.BlocklistEntry", b =>
{
b.HasOne("BirthdayBot.Data.GuildConfig", "Guild")
.WithMany("BlockedUsers")
.HasForeignKey("GuildId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("banned_users_guild_id_fkey");
b.Navigation("Guild");
});
modelBuilder.Entity("BirthdayBot.Data.UserEntry", b => modelBuilder.Entity("BirthdayBot.Data.UserEntry", b =>
{ {
b.HasOne("BirthdayBot.Data.GuildConfig", "Guild") b.HasOne("BirthdayBot.Data.GuildConfig", "Guild")
@ -148,8 +120,6 @@ namespace BirthdayBot.Data.Migrations
modelBuilder.Entity("BirthdayBot.Data.GuildConfig", b => modelBuilder.Entity("BirthdayBot.Data.GuildConfig", b =>
{ {
b.Navigation("BlockedUsers");
b.Navigation("UserEntries"); b.Navigation("UserEntries");
}); });
#pragma warning restore 612, 618 #pragma warning restore 612, 618

View file

@ -150,8 +150,6 @@ public sealed class ShardInstance : IDisposable {
if (result.Error == InteractionCommandError.UnmetPrecondition) { if (result.Error == InteractionCommandError.UnmetPrecondition) {
var errReply = result.ErrorReason switch { var errReply = result.ErrorReason switch {
RequireBotModeratorAttribute.Error => RequireBotModeratorAttribute.Reply, RequireBotModeratorAttribute.Error => RequireBotModeratorAttribute.Reply,
EnforceBlockingAttribute.FailBlocked => EnforceBlockingAttribute.ReplyBlocked,
EnforceBlockingAttribute.FailModerated => EnforceBlockingAttribute.ReplyModerated,
RequireGuildContextAttribute.Error => RequireGuildContextAttribute.Reply, RequireGuildContextAttribute.Error => RequireGuildContextAttribute.Reply,
_ => result.ErrorReason _ => result.ErrorReason
}; };