From 815e57c3551d9b2b199f523e8fd8fd9e3912a6f5 Mon Sep 17 00:00:00 2001 From: Jay Madden Date: Sun, 30 Oct 2022 23:44:26 -0500 Subject: [PATCH] Bump d.py version and add auto role assign functionality (#799) --- .../Features/Guilds/Bot/Roles.cs | 5 +- .../Features/Roles/Bot/Details.cs | 9 +- .../Features/Roles/Bot/Edit.cs | 3 + .../Properties/launchSettings.json | 9 + .../Contexts/ClemBotContext.cs | 4 - ...165404_AddAutoRoleAssignedProp.Designer.cs | 875 ++++++++++++++++++ .../20221030165404_AddAutoRoleAssignedProp.cs | 46 + .../Migrations/ClemBotContextModelSnapshot.cs | 9 +- ClemBot.Api/ClemBot.Api.Data/Models/Role.cs | 6 +- ClemBot.Bot/bot/api/role_route.py | 13 + ClemBot.Bot/bot/clem_bot.py | 2 +- ClemBot.Bot/bot/cogs/assignable_roles_cog.py | 98 +- ClemBot.Bot/bot/cogs/manage_classes_cog.py | 6 +- ClemBot.Bot/bot/messaging/events.py | 37 +- .../bot/services/assignable_roles_service.py | 24 - .../bot/services/moderation_service.py | 2 +- .../bot/services/role_handling_service.py | 25 + .../bot/services/user_handling_service.py | 6 +- .../bot/services/welcome_message_service.py | 2 +- ClemBot.Bot/poetry.lock | 159 ++-- ClemBot.Bot/pyproject.toml | 2 +- ClemBot.Docs/docs/Roles/AutoAssignedRoles.md | 72 ++ .../UserAssignableRoles.md} | 6 +- ClemBot.Docs/docs/Roles/index.md | 1 + 24 files changed, 1266 insertions(+), 155 deletions(-) create mode 100644 ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.Designer.cs create mode 100644 ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.cs delete mode 100644 ClemBot.Bot/bot/services/assignable_roles_service.py create mode 100644 ClemBot.Docs/docs/Roles/AutoAssignedRoles.md rename ClemBot.Docs/docs/{AssignableRoles.md => Roles/UserAssignableRoles.md} (93%) create mode 100644 ClemBot.Docs/docs/Roles/index.md diff --git a/ClemBot.Api/ClemBot.Api.Core/Features/Guilds/Bot/Roles.cs b/ClemBot.Api/ClemBot.Api.Core/Features/Guilds/Bot/Roles.cs index 9f82cdfe..6761ac38 100644 --- a/ClemBot.Api/ClemBot.Api.Core/Features/Guilds/Bot/Roles.cs +++ b/ClemBot.Api/ClemBot.Api.Core/Features/Guilds/Bot/Roles.cs @@ -23,6 +23,8 @@ public class Model public string? Name { get; init; } public bool IsAssignable { get; init; } + + public bool IsAutoAssigned { get; init; } } public record QueryHandler(ClemBotContext _context) @@ -45,7 +47,8 @@ public async Task>> Handle(Query request, { Id = role.Id, Name = role.Name, - IsAssignable = role.IsAssignable ?? false + IsAssignable = role.IsAssignable, + IsAutoAssigned = role.IsAutoAssigned })); } } diff --git a/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Details.cs b/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Details.cs index fb91f744..ccf05822 100644 --- a/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Details.cs +++ b/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Details.cs @@ -26,6 +26,8 @@ public class Model public bool Admin { get; init; } public bool IsAssignable { get; init; } + + public bool IsAutoAssigned { get; init; } } public record QueryHandler(ClemBotContext _context) : IRequestHandler> @@ -34,19 +36,20 @@ public async Task> Handle(Query request, CancellationToken ca { var role = await _context.Roles .Where(x => x.Id == request.Id) - .FirstAsync(); + .FirstOrDefaultAsync(); if (role is null) { return QueryResult.NotFound(); } - return QueryResult.Success(new Model() + return QueryResult.Success(new Model { Id = role.Id, Name = role.Name, GuildId = role.GuildId, - IsAssignable = role.IsAssignable ?? false, + IsAssignable = role.IsAssignable, + IsAutoAssigned = role.IsAutoAssigned, Admin = role.Admin }); } diff --git a/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Edit.cs b/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Edit.cs index 59cb57c9..779ca30f 100644 --- a/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Edit.cs +++ b/ClemBot.Api/ClemBot.Api.Core/Features/Roles/Bot/Edit.cs @@ -27,6 +27,8 @@ public class Command : IRequest> public bool? Admin { get; set; } = null; public bool? Assignable { get; set; } = null; + + public bool? AutoAssigned { get; set; } = null; } public record Handler(ClemBotContext _context) : IRequestHandler> @@ -44,6 +46,7 @@ public async Task> Handle(Command request, CancellationToken role.Name = request.Name ?? role.Name; role.Admin = request.Admin ?? role.Admin; role.IsAssignable = request.Assignable ?? role.IsAssignable; + role.IsAutoAssigned = request.AutoAssigned ?? role.IsAutoAssigned; await _context.SaveChangesAsync(); diff --git a/ClemBot.Api/ClemBot.Api.Core/Properties/launchSettings.json b/ClemBot.Api/ClemBot.Api.Core/Properties/launchSettings.json index 530c4e01..816b36be 100644 --- a/ClemBot.Api/ClemBot.Api.Core/Properties/launchSettings.json +++ b/ClemBot.Api/ClemBot.Api.Core/Properties/launchSettings.json @@ -26,6 +26,15 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "ClemBot.Api.Core (No Browser)": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": false, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } } } } diff --git a/ClemBot.Api/ClemBot.Api.Data/Contexts/ClemBotContext.cs b/ClemBot.Api/ClemBot.Api.Data/Contexts/ClemBotContext.cs index 03d3ef4d..0d2f2c7b 100644 --- a/ClemBot.Api/ClemBot.Api.Data/Contexts/ClemBotContext.cs +++ b/ClemBot.Api/ClemBot.Api.Data/Contexts/ClemBotContext.cs @@ -44,10 +44,6 @@ static ClemBotContext() protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity() - .Property(p => p.IsAssignable) - .HasDefaultValue(true); - modelBuilder.Entity() .HasMany(p => p.Users) .WithMany(p => p.Guilds) diff --git a/ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.Designer.cs b/ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.Designer.cs new file mode 100644 index 00000000..2ef46d49 --- /dev/null +++ b/ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.Designer.cs @@ -0,0 +1,875 @@ +// +using System; +using ClemBot.Api.Common.Enums; +using ClemBot.Api.Data.Contexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NodaTime; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ClemBot.Api.Data.Migrations +{ + [DbContext(typeof(ClemBotContext))] + [Migration("20221030165404_AddAutoRoleAssignedProp")] + partial class AddAutoRoleAssignedProp + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "bot_auth_claims", new[] { "designated_channel_view", "designated_channel_modify", "custom_prefix_set", "welcome_message_view", "welcome_message_modify", "tag_add", "tag_delete", "tag_transfer", "assignable_roles_add", "assignable_roles_delete", "delete_message", "emote_add", "claims_view", "claims_modify", "manage_class_add", "moderation_warn", "moderation_ban", "moderation_mute", "moderation_purge", "moderation_infraction_view", "moderation_infraction_view_self", "dashboard_view", "dashboard_edit", "guild_settings_view", "guild_settings_edit", "custom_tag_prefix_set", "command_restrictions_edit", "bypass_disabled_commands" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "command_restriction_type", new[] { "white_list", "black_list" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "config_settings", new[] { "allow_embed_links" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "designated_channels", new[] { "message_log", "moderation_log", "user_join_log", "user_leave_log", "starboard", "server_join_log", "bot_dm_log" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "infraction_type", new[] { "ban", "mute", "warn" }); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsThread") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("boolean") + .HasComputedColumnSql("\"Channels\".\"ParentId\" IS NOT null", true); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ParentId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("ParentId"); + + b.ToTable("Channels"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.ClaimsMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Claim") + .HasColumnType("bot_auth_claims"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("ClaimsMappings"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CommandInvocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("CommandName") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("CommandInvocations"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CommandRestriction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("CommandName") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RestrictionType") + .HasColumnType("command_restriction_type"); + + b.Property("SilentlyFail") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("GuildId"); + + b.ToTable("CommandRestrictions"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CustomPrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Prefix") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("CustomPrefixs"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CustomTagPrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("TagPrefix") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("CustomTagPrefixs"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.DesignatedChannelMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("Type") + .HasColumnType("designated_channels"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.ToTable("DesignatedChannelMappings"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Guild", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OwnerId") + .HasColumnType("numeric(20,0)"); + + b.Property("WelcomeMessage") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Guilds"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.GuildSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Setting") + .HasColumnType("config_settings"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("GuildSettings"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.GuildUser", b => + { + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("GuildId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("GuildUser"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Infraction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)"); + + b.Property("Duration") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("SubjectId") + .HasColumnType("numeric(20,0)"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("infraction_type"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("GuildId"); + + b.HasIndex("SubjectId"); + + b.ToTable("Infractions"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.MessageContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("MessageId"); + + b.ToTable("MessageContents"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Dispatched") + .HasColumnType("boolean"); + + b.Property("Link") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)"); + + b.Property("Admin") + .HasColumnType("boolean"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsAssignable") + .HasColumnType("boolean"); + + b.Property("IsAutoAssigned") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.RoleUser", b => + { + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("RoleId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("RoleUser"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.SlotScore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Score") + .HasColumnType("numeric(20,0)"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("SlotScores"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.TagUse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("TagId") + .HasColumnType("integer"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("TagId"); + + b.HasIndex("UserId"); + + b.ToTable("TagUses"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Channel", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("Channels") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.Channel", "Parent") + .WithMany() + .HasForeignKey("ParentId"); + + b.Navigation("Guild"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.ClaimsMapping", b => + { + b.HasOne("ClemBot.Api.Data.Models.Role", "Role") + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CommandRestriction", b => + { + b.HasOne("ClemBot.Api.Data.Models.Channel", "Channel") + .WithMany() + .HasForeignKey("ChannelId"); + + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CustomPrefix", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("CustomPrefixes") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.CustomTagPrefix", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("CustomTagPrefixes") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.DesignatedChannelMapping", b => + { + b.HasOne("ClemBot.Api.Data.Models.Channel", "Channel") + .WithMany("DesignatedChannels") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.GuildSetting", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("GuildSettings") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.GuildUser", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("GuildUsers") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany("GuildUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Infraction", b => + { + b.HasOne("ClemBot.Api.Data.Models.User", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("Infractions") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "Subject") + .WithMany() + .HasForeignKey("SubjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Guild"); + + b.Navigation("Subject"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Message", b => + { + b.HasOne("ClemBot.Api.Data.Models.Channel", "Channel") + .WithMany("Messages") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("Messages") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany("Messages") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.MessageContent", b => + { + b.HasOne("ClemBot.Api.Data.Models.Message", "Message") + .WithMany("Contents") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Message"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Reminder", b => + { + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Role", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("Roles") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.RoleUser", b => + { + b.HasOne("ClemBot.Api.Data.Models.Role", "Role") + .WithMany("RoleUsers") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany("RoleUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.SlotScore", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Tag", b => + { + b.HasOne("ClemBot.Api.Data.Models.Guild", "Guild") + .WithMany("Tags") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.TagUse", b => + { + b.HasOne("ClemBot.Api.Data.Models.Channel", "Channel") + .WithMany() + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.Tag", "Tag") + .WithMany("TagUses") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ClemBot.Api.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Channel", b => + { + b.Navigation("DesignatedChannels"); + + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Guild", b => + { + b.Navigation("Channels"); + + b.Navigation("CustomPrefixes"); + + b.Navigation("CustomTagPrefixes"); + + b.Navigation("GuildSettings"); + + b.Navigation("GuildUsers"); + + b.Navigation("Infractions"); + + b.Navigation("Messages"); + + b.Navigation("Roles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Message", b => + { + b.Navigation("Contents"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Role", b => + { + b.Navigation("Claims"); + + b.Navigation("RoleUsers"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.Tag", b => + { + b.Navigation("TagUses"); + }); + + modelBuilder.Entity("ClemBot.Api.Data.Models.User", b => + { + b.Navigation("GuildUsers"); + + b.Navigation("Messages"); + + b.Navigation("RoleUsers"); + + b.Navigation("Tags"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.cs b/ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.cs new file mode 100644 index 00000000..e753430b --- /dev/null +++ b/ClemBot.Api/ClemBot.Api.Data/Migrations/20221030165404_AddAutoRoleAssignedProp.cs @@ -0,0 +1,46 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ClemBot.Api.Data.Migrations +{ + public partial class AddAutoRoleAssignedProp : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IsAssignable", + table: "Roles", + type: "boolean", + nullable: false, + defaultValue: false, + oldClrType: typeof(bool), + oldType: "boolean", + oldNullable: true, + oldDefaultValue: true); + + migrationBuilder.AddColumn( + name: "IsAutoAssigned", + table: "Roles", + type: "boolean", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsAutoAssigned", + table: "Roles"); + + migrationBuilder.AlterColumn( + name: "IsAssignable", + table: "Roles", + type: "boolean", + nullable: true, + defaultValue: true, + oldClrType: typeof(bool), + oldType: "boolean"); + } + } +} diff --git a/ClemBot.Api/ClemBot.Api.Data/Migrations/ClemBotContextModelSnapshot.cs b/ClemBot.Api/ClemBot.Api.Data/Migrations/ClemBotContextModelSnapshot.cs index ff638abb..f256f9ef 100644 --- a/ClemBot.Api/ClemBot.Api.Data/Migrations/ClemBotContextModelSnapshot.cs +++ b/ClemBot.Api/ClemBot.Api.Data/Migrations/ClemBotContextModelSnapshot.cs @@ -396,10 +396,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("GuildId") .HasColumnType("numeric(20,0)"); - b.Property("IsAssignable") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true); + b.Property("IsAssignable") + .HasColumnType("boolean"); + + b.Property("IsAutoAssigned") + .HasColumnType("boolean"); b.Property("Name") .HasColumnType("text"); diff --git a/ClemBot.Api/ClemBot.Api.Data/Models/Role.cs b/ClemBot.Api/ClemBot.Api.Data/Models/Role.cs index 03d238f9..4f6c7bca 100644 --- a/ClemBot.Api/ClemBot.Api.Data/Models/Role.cs +++ b/ClemBot.Api/ClemBot.Api.Data/Models/Role.cs @@ -8,7 +8,9 @@ public class Role public string Name { get; set; } - public bool? IsAssignable { get; set; } = false; + public bool IsAssignable { get; set; } + + public bool IsAutoAssigned { get; set; } public bool Admin { get; set; } @@ -19,4 +21,4 @@ public class Role public List RoleUsers { get; set; } public List Claims { get; set; } -} \ No newline at end of file +} diff --git a/ClemBot.Bot/bot/api/role_route.py b/ClemBot.Bot/bot/api/role_route.py index 84d59be8..834b5ee3 100644 --- a/ClemBot.Bot/bot/api/role_route.py +++ b/ClemBot.Bot/bot/api/role_route.py @@ -29,6 +29,11 @@ async def set_assignable(self, role_id: int, assignable: bool, **kwargs: t.Any) await self._client.patch("bot/roles", data=json, **kwargs) + async def set_auto_assigned(self, role_id: int, auto_assigned: bool, **kwargs: t.Any) -> None: + json = {"Id": role_id, "AutoAssigned": auto_assigned} + + await self._client.patch("bot/roles", data=json, **kwargs) + async def remove_role(self, role_id: int, **kwargs: t.Any) -> None: await self._client.delete(f"bot/roles/{role_id}", **kwargs) @@ -43,6 +48,14 @@ async def get_guilds_assignable_roles(self, guild_id: int) -> list[Role] | None: return [Role(**r) for r in roles if r["isAssignable"]] + async def get_guilds_auto_assigned_roles(self, guild_id: int) -> list[Role]: + roles = await self._client.get(f"bot/guilds/{guild_id}/roles") + + if not roles: + return [] + + return [Role(**r) for r in roles if r["isAutoAssigned"]] + async def check_role_assignable(self, role_id: int) -> bool | None: roles = await self._client.get(f"bot/roles/{role_id}") diff --git a/ClemBot.Bot/bot/clem_bot.py b/ClemBot.Bot/bot/clem_bot.py index 2b53af24..0467d77f 100644 --- a/ClemBot.Bot/bot/clem_bot.py +++ b/ClemBot.Bot/bot/clem_bot.py @@ -328,7 +328,7 @@ async def on_thread_update(self, before: discord.Thread, after: discord.Thread) ) async def on_member_join(self, user: discord.Member) -> None: - await self.publish_to_queue_with_error(Events.on_user_joined, user.guild.id, user) + await self.publish_to_queue_with_error(Events.on_initial_user_join, user.guild.id, user) async def on_member_remove(self, user: discord.Member) -> None: await self.publish_to_queue_with_error(Events.on_user_removed, user.guild.id, user) diff --git a/ClemBot.Bot/bot/cogs/assignable_roles_cog.py b/ClemBot.Bot/bot/cogs/assignable_roles_cog.py index a21eeb65..12d7620c 100644 --- a/ClemBot.Bot/bot/cogs/assignable_roles_cog.py +++ b/ClemBot.Bot/bot/cogs/assignable_roles_cog.py @@ -9,6 +9,7 @@ from bot.clem_bot import ClemBot from bot.consts import Claims, Colors from bot.messaging.events import Events +from bot.models.role_models import Role from bot.utils.helpers import chunk_sequence from bot.utils.logging_utils import get_logger @@ -224,7 +225,7 @@ async def set_role(self, ctx: ext.ClemBotCtx, role: discord.Role) -> None: async def add_role(self, ctx: ext.ClemBotCtx, role: discord.Role) -> None: assert isinstance(ctx.author, discord.Member) - await ctx.author.add_roles(t.cast(discord.abc.Snowflake, role)) + await ctx.author.add_roles(role) embed = discord.Embed(title="Role Added :white_check_mark:", color=Colors.ClemsonOrange) embed.add_field(name="Role: ", value=f"{role.mention} :arrow_right:") @@ -235,7 +236,7 @@ async def add_role(self, ctx: ext.ClemBotCtx, role: discord.Role) -> None: async def remove_role(self, ctx: ext.ClemBotCtx, role: discord.Role) -> None: assert isinstance(ctx.author, discord.Member) - await ctx.author.remove_roles(t.cast(discord.abc.Snowflake, role)) + await ctx.author.remove_roles(role) embed = discord.Embed(title="Role Removed :white_check_mark:", color=Colors.ClemsonOrange) embed.add_field(name="Role: ", value=f"{role.mention} :arrow_left:") @@ -250,7 +251,7 @@ async def remove_role(self, ctx: ext.ClemBotCtx, role: discord.Role) -> None: @ext.short_help("Marks a role as user assignable") @ext.example("roles add @SomeExampleRole") async def add(self, ctx: ext.ClemBotCtx, *, role: discord.Role) -> None: - await self.bot.messenger.publish(Events.on_assignable_role_add, role) + await self.bot.role_route.set_assignable(role.id, True, raise_on_error=True) title = f"Role @{role.name} Added as assignable :white_check_mark:" embed = discord.Embed(title=title, color=Colors.ClemsonOrange) @@ -263,13 +264,102 @@ async def add(self, ctx: ext.ClemBotCtx, *, role: discord.Role) -> None: @ext.short_help("Removes a role as user assignable") @ext.example("roles delete @SomeExampleRole") async def remove(self, ctx: ext.ClemBotCtx, *, role: discord.Role) -> None: - await self.bot.messenger.publish(Events.on_assignable_role_remove, role) + await self.bot.role_route.set_assignable(role.id, False, raise_on_error=True) title = f"Role @{role.name} Removed as assignable :white_check_mark:" embed = discord.Embed(title=title, color=Colors.ClemsonOrange) await ctx.send(embed=embed) + @roles.group(invoke_without_command=True, case_insensitive=True) + @ext.long_help("Command to list all currently auto assigned roles in the guild") + @ext.short_help("Removes a role as auto assigned") + @ext.example("roles auto") + async def auto(self, ctx: ext.ClemBotCtx) -> None: + roles = await self.bot.role_route.get_guilds_auto_assigned_roles(ctx.guild.id) + + if not roles: + embed = discord.Embed( + title="No roles are currently auto assigned on join", color=Colors.ClemsonOrange + ) + embed.add_field(name="Available:", value="No currently auto assigned roles.") + await ctx.send(embed=embed) + return + + pages = [] + if roles: + mentions: list[str] = [] + for role in roles: + d_role = ctx.guild.get_role(role.id) + + if not d_role: + mentions.append(role.name) + continue + + mentions.append(d_role.mention) + + for chunk in chunk_sequence(mentions, ROLE_LIST_CHUNK_SIZE): + embed = discord.Embed( + title="Roles auto assigned on join", color=Colors.ClemsonOrange + ) # new + embed.add_field(name="Auto roles:", value="\n".join(chunk), inline=True) + pages.append(embed) + + # Call paginate service + await self.bot.messenger.publish( + Events.on_set_pageable_embed, + pages=pages, + author=ctx.author, + channel=ctx.channel, + timeout=360, + ) + + @auto.command(name="add", aliases=["create"]) + @ext.required_claims(Claims.assignable_roles_add) + @ext.long_help("Command to add a role as auto assigned in the current guild") + @ext.short_help("Marks a role as auto assigned") + @ext.example("roles auto add @SomeExampleRole") + async def auto_add(self, ctx: ext.ClemBotCtx, *, role: discord.Role) -> None: + + roles = await self.bot.role_route.get_guilds_auto_assigned_roles(ctx.guild.id) + + if role.id in [r.id for r in roles]: + embed = discord.Embed( + title=f"Error: @{role.name} already set as auto assigned", color=Colors.Error + ) + await ctx.send(embed=embed) + return + + await self.bot.role_route.set_auto_assigned(role.id, True) + + title = f"Role @{role.name} Added as an auto assigned on join role :white_check_mark:" + embed = discord.Embed(title=title, color=Colors.ClemsonOrange) + + await ctx.send(embed=embed) + + @auto.command(name="remove", aliases=["delete"]) + @ext.required_claims(Claims.assignable_roles_delete) + @ext.long_help("Command to remove a role as auto assigned in the current guild") + @ext.short_help("Removes a role as auto assigned") + @ext.example("roles auto remove @SomeExampleRole") + async def auto_remove(self, ctx: ext.ClemBotCtx, role: discord.Role) -> None: + + roles = await self.bot.role_route.get_guilds_auto_assigned_roles(ctx.guild.id) + + if not role.id in [r.id for r in roles]: + embed = discord.Embed( + title=f"Error: @{role.name} not set as auto assigned", color=Colors.Error + ) + await ctx.send(embed=embed) + return + + await self.bot.role_route.set_auto_assigned(role.id, False) + + title = f"Role @{role.name} Removed as an auto assigned on join role :white_check_mark:" + embed = discord.Embed(title=title, color=Colors.ClemsonOrange) + + await ctx.send(embed=embed) + async def setup(bot: ClemBot) -> None: await bot.add_cog(AssignableRolesCog(bot)) diff --git a/ClemBot.Bot/bot/cogs/manage_classes_cog.py b/ClemBot.Bot/bot/cogs/manage_classes_cog.py index 98783416..9cf273ff 100644 --- a/ClemBot.Bot/bot/cogs/manage_classes_cog.py +++ b/ClemBot.Bot/bot/cogs/manage_classes_cog.py @@ -303,12 +303,12 @@ async def create_role(self, ctx: ext.ClemBotCtx, class_repr: ClassType) -> disco try: # wait a split second to insert the role in the db await asyncio.sleep(0.25) - await self.bot.messenger.publish(Events.on_assignable_role_add, role) + await self.bot.role_route.set_assignable(role.id, True, raise_on_error=True) except: # If the marking of the role as assignable fails # Wait a second for the api to finish inserting the role then try it again await asyncio.sleep(1) - await self.bot.messenger.publish(Events.on_assignable_role_add, role) + await self.bot.role_route.set_assignable(role.id, True, raise_on_error=True) return role @@ -321,7 +321,7 @@ async def sync_perms( assert cleanup - await self.bot.messenger.publish(Events.on_assignable_role_add, cleanup) + await self.bot.role_route.set_assignable(cleanup.id, True, raise_on_error=True) # Upon detecting first time user, show embed showing how to use commands embed = discord.Embed( diff --git a/ClemBot.Bot/bot/messaging/events.py b/ClemBot.Bot/bot/messaging/events.py index 05e8a717..e8ebafc0 100644 --- a/ClemBot.Bot/bot/messaging/events.py +++ b/ClemBot.Bot/bot/messaging/events.py @@ -214,15 +214,26 @@ def on_guild_role_delete(self) -> str: return "on_guild_role_delete" @property - def on_user_joined(self) -> str: + def on_initial_user_join(self) -> str: """ Published whenever a new user joins a guild Args: - user (User) – The user who joined or left. + user (User) – The user who joined a guild """ - return "on_user_joined" + return "on_initial_user_join" + + @property + def on_user_join_initialized(self) -> str: + """ + Published after a new guild join has been fully initialized in the database + + Args: + + user (User) – The user who joined a guild + """ + return "on_user_joined_initialized" @property def on_user_removed(self) -> str: @@ -310,26 +321,6 @@ def on_set_custom_prefix(self) -> str: """ return "on_set_custom_prefix" - @property - def on_assignable_role_add(self) -> str: - """ - Pulbished when a new role is marked as set to be marked as assignable - - Args: - role (discord.Role) The role to mark as assignable - """ - return "on_assignable_role_add" - - @property - def on_assignable_role_remove(self) -> str: - """ - Published when a role is marked as set to be removed as assignable - - Args: - role (discord.Role) The role to remove as assignable - """ - return "on_assignable_role_remove" - @property def on_set_deletable(self) -> str: """ diff --git a/ClemBot.Bot/bot/services/assignable_roles_service.py b/ClemBot.Bot/bot/services/assignable_roles_service.py deleted file mode 100644 index 1f1da3fa..00000000 --- a/ClemBot.Bot/bot/services/assignable_roles_service.py +++ /dev/null @@ -1,24 +0,0 @@ -import discord - -from bot.clem_bot import ClemBot -from bot.messaging.events import Events -from bot.services.base_service import BaseService -from bot.utils.logging_utils import get_logger - -log = get_logger(__name__) - - -class AssignableRolesService(BaseService): - def __init__(self, *, bot: ClemBot) -> None: - super().__init__(bot) - - @BaseService.listener(Events.on_assignable_role_add) - async def assignable_role_add(self, role: discord.Role) -> None: - await self.bot.role_route.set_assignable(role.id, True, raise_on_error=True) - - @BaseService.listener(Events.on_assignable_role_remove) - async def assignable_role_remove(self, role: discord.Role) -> None: - await self.bot.role_route.set_assignable(role.id, False, raise_on_error=True) - - async def load_service(self) -> None: - pass diff --git a/ClemBot.Bot/bot/services/moderation_service.py b/ClemBot.Bot/bot/services/moderation_service.py index 50b16178..a7bd5a9b 100644 --- a/ClemBot.Bot/bot/services/moderation_service.py +++ b/ClemBot.Bot/bot/services/moderation_service.py @@ -165,7 +165,7 @@ async def on_bot_unmute( Events.on_send_in_designated_channel, DesignatedChannels.moderation_log, guild.id, embed ) - @BaseService.listener(Events.on_user_joined) + @BaseService.listener(Events.on_user_join_initialized) async def on_joined(self, user: discord.Member) -> None: mute_role = discord.utils.get(user.guild.roles, name=Moderation.mute_role_name) diff --git a/ClemBot.Bot/bot/services/role_handling_service.py b/ClemBot.Bot/bot/services/role_handling_service.py index 7a056738..597660e1 100644 --- a/ClemBot.Bot/bot/services/role_handling_service.py +++ b/ClemBot.Bot/bot/services/role_handling_service.py @@ -4,6 +4,7 @@ from bot.clem_bot import ClemBot from bot.messaging.events import Events from bot.services.base_service import BaseService +from bot.utils.log_serializers import log_role, log_user from bot.utils.logging_utils import get_logger log = get_logger(__name__) @@ -49,5 +50,29 @@ async def on_role_update(self, before: discord.Role, after: discord.Role) -> Non after.id, after.name, after.permissions.administrator, raise_on_error=True ) + @BaseService.listener(Events.on_user_join_initialized) + async def add_auto_assigned_roles(self, member: discord.Member) -> None: + roles = await self.bot.role_route.get_guilds_auto_assigned_roles(member.guild.id) + + d_roles: list[discord.Role] = [] + for r in roles: + d_role = member.guild.get_role(r.id) + + if not d_role: + log.warning( + "Invalid role id returned from database in auto assign handler Role: {role}", + role=r.id, + ) + continue + + d_roles.append(d_role) + + log.info( + "Auto adding roles: {roles} to member: {member}", + roles=[log_role(r) for r in d_roles], + member=log_user(member), + ) + await member.add_roles(*d_roles, reason="Adding auto join roles to user") + async def load_service(self) -> None: pass diff --git a/ClemBot.Bot/bot/services/user_handling_service.py b/ClemBot.Bot/bot/services/user_handling_service.py index 81993430..67070f75 100644 --- a/ClemBot.Bot/bot/services/user_handling_service.py +++ b/ClemBot.Bot/bot/services/user_handling_service.py @@ -28,7 +28,7 @@ def __init__(self, *, bot: ClemBot): super().__init__(bot) - @BaseService.listener(Events.on_user_joined) + @BaseService.listener(Events.on_initial_user_join) async def on_user_joined(self, user: discord.Member) -> None: log.info( '"{member}" has joined guild "{guild}"', @@ -46,6 +46,10 @@ async def on_user_joined(self, user: discord.Member) -> None: await self.notify_user_join(user) + # We have completed our setup steps, we can now broadcast + # this user to the rest of the bot for other handling steps + await self.messenger.publish(Events.on_user_join_initialized, user) + @BaseService.listener(Events.on_user_removed) async def on_user_removed(self, user: discord.Member) -> None: log.info( diff --git a/ClemBot.Bot/bot/services/welcome_message_service.py b/ClemBot.Bot/bot/services/welcome_message_service.py index 27310507..808aeff0 100644 --- a/ClemBot.Bot/bot/services/welcome_message_service.py +++ b/ClemBot.Bot/bot/services/welcome_message_service.py @@ -12,7 +12,7 @@ class WelcomeMessageService(BaseService): def __init__(self, *, bot: ClemBot): super().__init__(bot) - @BaseService.listener(Events.on_user_joined) + @BaseService.listener(Events.on_user_join_initialized) async def user_joined(self, user: discord.Member) -> None: message = await self.bot.welcome_message_route.get_welcome_message(user.guild.id) diff --git a/ClemBot.Bot/poetry.lock b/ClemBot.Bot/poetry.lock index 3c46eade..02e15f31 100644 --- a/ClemBot.Bot/poetry.lock +++ b/ClemBot.Bot/poetry.lock @@ -65,7 +65,7 @@ tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] [[package]] name = "astroid" -version = "2.12.10" +version = "2.12.12" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false @@ -149,11 +149,11 @@ lxml = ["lxml"] [[package]] name = "black" -version = "22.8.0" +version = "22.10.0" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" [package.dependencies] click = ">=8.0.0" @@ -224,11 +224,11 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "contextlib2" @@ -264,7 +264,7 @@ graph = ["objgraph (>=1.7.2)"] [[package]] name = "discord.py" -version = "2.1.0a4600+gc35ff4cf" +version = "2.1.0a4630+ge92a6266" description = "A Python wrapper for the Discord API" category = "main" optional = false @@ -283,8 +283,8 @@ voice = ["PyNaCl (>=1.3.0,<1.6)"] [package.source] type = "git" url = "https://github.com/Rapptz/discord.py.git" -reference = "c35ff4cfc637907ad797617df485f964ff26c301" -resolved_reference = "c35ff4cfc637907ad797617df485f964ff26c301" +reference = "e92a6266628d0cc99727c8eb88c2432a931138a0" +resolved_reference = "e92a6266628d0cc99727c8eb88c2432a931138a0" [[package]] name = "distlib" @@ -310,6 +310,17 @@ category = "main" optional = false python-versions = ">=2.7" +[[package]] +name = "exceptiongroup" +version = "1.0.0" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "filelock" version = "3.6.0" @@ -619,7 +630,7 @@ test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"] [[package]] name = "pandas-stubs" -version = "1.4.4.220919" +version = "1.5.1.221024" description = "Type annotations for pandas" category = "dev" optional = false @@ -694,14 +705,6 @@ category = "main" optional = false python-versions = "*" -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - [[package]] name = "pycodestyle" version = "2.8.0" @@ -735,14 +738,14 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pylint" -version = "2.15.3" +version = "2.15.5" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.7.2" [package.dependencies] -astroid = ">=2.12.10,<=2.14.0-dev0" +astroid = ">=2.12.12,<=2.14.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = ">=0.2" isort = ">=4.2.5,<6" @@ -776,7 +779,7 @@ python-versions = "*" [[package]] name = "pytest" -version = "7.1.3" +version = "7.2.0" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -785,11 +788,11 @@ python-versions = ">=3.7" [package.dependencies] attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] @@ -973,11 +976,11 @@ python-versions = ">=3.7" [[package]] name = "tomlkit" -version = "0.11.4" +version = "0.11.6" description = "Style preserving TOML library" category = "dev" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.6" [[package]] name = "tqdm" @@ -1006,7 +1009,7 @@ python-versions = ">=3.6" [[package]] name = "types-pillow" -version = "9.2.2" +version = "9.3.0.0" description = "Typing stubs for Pillow" category = "dev" optional = false @@ -1014,7 +1017,7 @@ python-versions = "*" [[package]] name = "types-python-dateutil" -version = "2.8.19" +version = "2.8.19.2" description = "Typing stubs for python-dateutil" category = "dev" optional = false @@ -1022,7 +1025,7 @@ python-versions = "*" [[package]] name = "types-pytz" -version = "2022.2.1.0" +version = "2022.5.0.0" description = "Typing stubs for pytz" category = "dev" optional = false @@ -1030,7 +1033,7 @@ python-versions = "*" [[package]] name = "types-requests" -version = "2.28.10" +version = "2.28.11.2" description = "Typing stubs for requests" category = "dev" optional = false @@ -1041,7 +1044,7 @@ types-urllib3 = "<1.27" [[package]] name = "types-urllib3" -version = "1.26.24" +version = "1.26.25.1" description = "Typing stubs for urllib3" category = "dev" optional = false @@ -1149,7 +1152,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [metadata] lock-version = "1.1" python-versions = ">=3.10,<3.11" -content-hash = "deb36299cecd8f1601f6e7fc4cc40ee121f3489ed4a355eeff87114f48d8f2de" +content-hash = "960d5f714838be659e114b3b0e0f1f2d2a6ac345ef89aa87da09958947a5e368" [metadata.files] aiohttp = [ @@ -1211,8 +1214,8 @@ asgiref = [ {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, ] astroid = [ - {file = "astroid-2.12.10-py3-none-any.whl", hash = "sha256:997e0c735df60d4a4caff27080a3afc51f9bdd693d3572a4a0b7090b645c36c5"}, - {file = "astroid-2.12.10.tar.gz", hash = "sha256:81f870105d892e73bf535da77a8261aa5bde838fa4ed12bb2f435291a098c581"}, + {file = "astroid-2.12.12-py3-none-any.whl", hash = "sha256:72702205200b2a638358369d90c222d74ebc376787af8fb2f7f2a86f7b5cc85f"}, + {file = "astroid-2.12.12.tar.gz", hash = "sha256:1c00a14f5a3ed0339d38d2e2e5b74ea2591df5861c0936bb292b84ccf3a78d83"}, ] async-timeout = [ {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, @@ -1239,29 +1242,27 @@ beautifulsoup4 = [ {file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"}, ] black = [ - {file = "black-22.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd"}, - {file = "black-22.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27"}, - {file = "black-22.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747"}, - {file = "black-22.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869"}, - {file = "black-22.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90"}, - {file = "black-22.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe"}, - {file = "black-22.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342"}, - {file = "black-22.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab"}, - {file = "black-22.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3"}, - {file = "black-22.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e"}, - {file = "black-22.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16"}, - {file = "black-22.8.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c"}, - {file = "black-22.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5"}, - {file = "black-22.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411"}, - {file = "black-22.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3"}, - {file = "black-22.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"}, - {file = "black-22.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c"}, - {file = "black-22.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497"}, - {file = "black-22.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c"}, - {file = "black-22.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41"}, - {file = "black-22.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec"}, - {file = "black-22.8.0-py3-none-any.whl", hash = "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4"}, - {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, ] cachecontrol = [ {file = "CacheControl-0.12.11-py2.py3-none-any.whl", hash = "sha256:2c75d6a8938cb1933c75c50184549ad42728a27e9f6b92fd677c3151aa72555b"}, @@ -1284,8 +1285,8 @@ click = [ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] contextlib2 = [ {file = "contextlib2-0.6.0-py2.py3-none-any.whl", hash = "sha256:9d2c67f18c1f9b6db1b46317f7f784aa82789d2ee5dea5d9c0f0f2a764eb862e"}, @@ -1311,6 +1312,10 @@ entrypoints = [ {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] +exceptiongroup = [ + {file = "exceptiongroup-1.0.0-py3-none-any.whl", hash = "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41"}, + {file = "exceptiongroup-1.0.0.tar.gz", hash = "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad"}, +] filelock = [ {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, @@ -1580,8 +1585,8 @@ pandas = [ {file = "pandas-1.3.4.tar.gz", hash = "sha256:a2aa18d3f0b7d538e21932f637fbfe8518d085238b429e4790a35e1e44a96ffc"}, ] pandas-stubs = [ - {file = "pandas-stubs-1.4.4.220919.tar.gz", hash = "sha256:562cd423054095f49294aa39672c413b0d81b3e8850b808ede663369bcad223c"}, - {file = "pandas_stubs-1.4.4.220919-py3-none-any.whl", hash = "sha256:cf90cf2d167f199cb2eb2826278271360eee5d5f975834096437105a7048e6da"}, + {file = "pandas-stubs-1.5.1.221024.tar.gz", hash = "sha256:a756ea4c7f2f973b9f9dfd64d724ba911e82e8ffa2e0188f56fadfdd9345771a"}, + {file = "pandas_stubs-1.5.1.221024-py3-none-any.whl", hash = "sha256:363e3833137375aebd6ab272fe89d94e88a443891a48d536c905e16ce2800cf6"}, ] pathspec = [ {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, @@ -1643,10 +1648,6 @@ pluggy = [ progress = [ {file = "progress-1.5.tar.gz", hash = "sha256:69ecedd1d1bbe71bf6313d88d1e6c4d2957b7f1d4f71312c211257f7dae64372"}, ] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] pycodestyle = [ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, @@ -1693,8 +1694,8 @@ pyflakes = [ {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, ] pylint = [ - {file = "pylint-2.15.3-py3-none-any.whl", hash = "sha256:7f6aad1d8d50807f7bc64f89ac75256a9baf8e6ed491cc9bc65592bc3f462cf1"}, - {file = "pylint-2.15.3.tar.gz", hash = "sha256:5fdfd44af182866999e6123139d265334267339f29961f00c89783155eacc60b"}, + {file = "pylint-2.15.5-py3-none-any.whl", hash = "sha256:c2108037eb074334d9e874dc3c783752cc03d0796c88c9a9af282d0f161a1004"}, + {file = "pylint-2.15.5.tar.gz", hash = "sha256:3b120505e5af1d06a5ad76b55d8660d44bf0f2fc3c59c2bdd94e39188ee3a4df"}, ] pyparsing = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, @@ -1705,8 +1706,8 @@ pyspellchecker = [ {file = "pyspellchecker-0.6.3.tar.gz", hash = "sha256:764dfe1bcbd4d860b74205402167d55a02910870c07b83678e7d6b5a4d471909"}, ] pytest = [ - {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, - {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, + {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, + {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, ] pytest-asyncio = [ {file = "pytest-asyncio-0.19.0.tar.gz", hash = "sha256:ac4ebf3b6207259750bc32f4c1d8fcd7e79739edbc67ad0c58dd150b1d072fed"}, @@ -1869,8 +1870,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [ - {file = "tomlkit-0.11.4-py3-none-any.whl", hash = "sha256:25d4e2e446c453be6360c67ddfb88838cfc42026322770ba13d1fbd403a93a5c"}, - {file = "tomlkit-0.11.4.tar.gz", hash = "sha256:3235a9010fae54323e727c3ac06fb720752fe6635b3426e379daec60fbd44a83"}, + {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, + {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, ] tqdm = [ {file = "tqdm-4.64.0-py2.py3-none-any.whl", hash = "sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"}, @@ -1903,24 +1904,24 @@ typed-ast = [ {file = "typed_ast-1.5.3.tar.gz", hash = "sha256:27f25232e2dd0edfe1f019d6bfaaf11e86e657d9bdb7b0956db95f560cceb2b3"}, ] types-pillow = [ - {file = "types-Pillow-9.2.2.tar.gz", hash = "sha256:6b525b0951ada076f3aefe2347e0bff6231283ce959ad8577a4416604acc673c"}, - {file = "types_Pillow-9.2.2-py3-none-any.whl", hash = "sha256:bfe14afa1e9047a52b3dc326c93b4f57db72641794e194f11b511f68b0061814"}, + {file = "types-Pillow-9.3.0.0.tar.gz", hash = "sha256:0851a1b3ff002253a7af8f7eaf74d79fb761430933bd1aeb73d853a17f2a0a9d"}, + {file = "types_Pillow-9.3.0.0-py3-none-any.whl", hash = "sha256:df09de7e557706c16fb30db887327c7f1c81e8ebc703d9d4739bfda7cad0e733"}, ] types-python-dateutil = [ - {file = "types-python-dateutil-2.8.19.tar.gz", hash = "sha256:bfd3eb39c7253aea4ba23b10f69b017d30b013662bb4be4ab48b20bbd763f309"}, - {file = "types_python_dateutil-2.8.19-py3-none-any.whl", hash = "sha256:6284df1e4783d8fc6e587f0317a81333856b872a6669a282f8a325342bce7fa8"}, + {file = "types-python-dateutil-2.8.19.2.tar.gz", hash = "sha256:e6e32ce18f37765b08c46622287bc8d8136dc0c562d9ad5b8fd158c59963d7a7"}, + {file = "types_python_dateutil-2.8.19.2-py3-none-any.whl", hash = "sha256:3f4dbe465e7e0c6581db11fd7a4855d1355b78712b3f292bd399cd332247e9c0"}, ] types-pytz = [ - {file = "types-pytz-2022.2.1.0.tar.gz", hash = "sha256:47cfb19c52b9f75896440541db392fd312a35b279c6307a531db71152ea63e2b"}, - {file = "types_pytz-2022.2.1.0-py3-none-any.whl", hash = "sha256:50ead2254b524a3d4153bc65d00289b66898060d2938e586170dce918dbaf3b3"}, + {file = "types-pytz-2022.5.0.0.tar.gz", hash = "sha256:0c163b15d3e598e6cc7074a99ca9ec72b25dc1b446acc133b827667af0b7b09a"}, + {file = "types_pytz-2022.5.0.0-py3-none-any.whl", hash = "sha256:a8e1fe6a1b270fbfaf2553b20ad0f1316707cc320e596da903bb17d7373fed2d"}, ] types-requests = [ - {file = "types-requests-2.28.10.tar.gz", hash = "sha256:97d8f40aa1ffe1e58c3726c77d63c182daea9a72d9f1fa2cafdea756b2a19f2c"}, - {file = "types_requests-2.28.10-py3-none-any.whl", hash = "sha256:45b485725ed58752f2b23461252f1c1ad9205b884a1e35f786bb295525a3e16a"}, + {file = "types-requests-2.28.11.2.tar.gz", hash = "sha256:fdcd7bd148139fb8eef72cf4a41ac7273872cad9e6ada14b11ff5dfdeee60ed3"}, + {file = "types_requests-2.28.11.2-py3-none-any.whl", hash = "sha256:14941f8023a80b16441b3b46caffcbfce5265fd14555844d6029697824b5a2ef"}, ] types-urllib3 = [ - {file = "types-urllib3-1.26.24.tar.gz", hash = "sha256:a1b3aaea7dda3eb1b51699ee723aadd235488e4dc4648e030f09bc429ecff42f"}, - {file = "types_urllib3-1.26.24-py3-none-any.whl", hash = "sha256:cf7918503d02d3576e503bbfb419b0e047c4617653bba09624756ab7175e15c9"}, + {file = "types-urllib3-1.26.25.1.tar.gz", hash = "sha256:a948584944b2412c9a74b9cf64f6c48caf8652cb88b38361316f6d15d8a184cd"}, + {file = "types_urllib3-1.26.25.1-py3-none-any.whl", hash = "sha256:f6422596cc9ee5fdf68f9d547f541096a20c2dcfd587e37c804c9ea720bf5cb2"}, ] typing-extensions = [ {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"}, diff --git a/ClemBot.Bot/pyproject.toml b/ClemBot.Bot/pyproject.toml index 87c71eee..13700c73 100644 --- a/ClemBot.Bot/pyproject.toml +++ b/ClemBot.Bot/pyproject.toml @@ -7,7 +7,7 @@ license = "MIT" [tool.poetry.dependencies] python = ">=3.10,<3.11" -"discord.py" = { git = "https://github.com/Rapptz/discord.py.git", branch = "c35ff4cfc637907ad797617df485f964ff26c301" } +"discord.py" = { git = "https://github.com/Rapptz/discord.py.git", branch = "e92a6266628d0cc99727c8eb88c2432a931138a0" } aiohttp = "3.7.4" aiosqlite = "0.12.0" appdirs = "1.4.3" diff --git a/ClemBot.Docs/docs/Roles/AutoAssignedRoles.md b/ClemBot.Docs/docs/Roles/AutoAssignedRoles.md new file mode 100644 index 00000000..12913ebb --- /dev/null +++ b/ClemBot.Docs/docs/Roles/AutoAssignedRoles.md @@ -0,0 +1,72 @@ +--- +sidebar_position: 6 +--- +# Auto Assigned Roles + +## Overview + +Server admins may want users to be auto assigned roles on join. This functionality is exposed throught the roles auto subcommand grouping. + +## Commands + +### Roles auto +Shows all currently auto assigned roles in a server + +#### Format +```txt title="List all auto assigned roles in the server" +!roles auto +``` +#### Example + +``` +!role auto +``` +### Auto add +Mark a server role as assignable + +:::note +Note: This is the admin command to **MARK** a role as auto assigned on join. +If you would like to give yourself a role please see the [UserAssignableRoles](./UserAssignableRoles.md) section on adding an assignable role to yourself. +::: + +#### Aliases +* `create` + +#### Required [Claims](../Claims.md) +* `assignable_role_add` + +#### Format + +``` +!role auto add +``` +#### Example + +``` +!role auto add MyRole +``` + +### Auto remove +Remove a server role as assignable + +:::note +This is the admin command to **REMOVE** a role as auto assigned on join. +If you would like to give yourself a role please see the [UserAssignableRoles](./UserAssignableRoles.md) section on adding an assignable role to yourself. +::: + +#### Aliases +* `delete` + +#### Required [Claims](../Claims.md) +* `assignable_role_delete` + +#### Format + +``` +!role auto delete +``` +#### Example + +``` +!role auto delete MyRole +``` \ No newline at end of file diff --git a/ClemBot.Docs/docs/AssignableRoles.md b/ClemBot.Docs/docs/Roles/UserAssignableRoles.md similarity index 93% rename from ClemBot.Docs/docs/AssignableRoles.md rename to ClemBot.Docs/docs/Roles/UserAssignableRoles.md index 9093a5f6..fbc7f5b0 100644 --- a/ClemBot.Docs/docs/AssignableRoles.md +++ b/ClemBot.Docs/docs/Roles/UserAssignableRoles.md @@ -1,7 +1,7 @@ --- sidebar_position: 6 --- -# Assignable Roles +# User Assignable Roles ## Overview @@ -47,7 +47,7 @@ If you would like to give yourself a role please see the above section on adding #### Aliases * `create` -#### Required [Claims](./Claims.md) +#### Required [Claims](../Claims.md) * `assignable_role_add` #### Format @@ -72,7 +72,7 @@ If you would like to remove a role from yourself please see the above section on #### Aliases * `delete` -#### Required [Claims](./Claims.md) +#### Required [Claims](../Claims.md) * `assignable_role_delete` #### Format diff --git a/ClemBot.Docs/docs/Roles/index.md b/ClemBot.Docs/docs/Roles/index.md new file mode 100644 index 00000000..a6139a3a --- /dev/null +++ b/ClemBot.Docs/docs/Roles/index.md @@ -0,0 +1 @@ +# Assigned Roles