diff --git a/Cocotte/Cocotte.csproj b/Cocotte/Cocotte.csproj index 7f7576f..9399762 100644 --- a/Cocotte/Cocotte.csproj +++ b/Cocotte/Cocotte.csproj @@ -9,6 +9,18 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + PreserveNewest + + diff --git a/Cocotte/Migrations/20230320145030_InitialCreate.Designer.cs b/Cocotte/Migrations/20230320145030_InitialCreate.Designer.cs new file mode 100644 index 0000000..b20a371 --- /dev/null +++ b/Cocotte/Migrations/20230320145030_InitialCreate.Designer.cs @@ -0,0 +1,122 @@ +// +using Cocotte.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Cocotte.Migrations +{ + [DbContext(typeof(CocotteContext))] + [Migration("20230320145030_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.Activity", b => + { + b.Property("ActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActivityName") + .HasColumnType("INTEGER"); + + b.Property("ActivityType") + .HasColumnType("INTEGER"); + + b.Property("CreatorId") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("MaxPlayers") + .HasColumnType("INTEGER"); + + b.HasKey("ActivityId"); + + b.ToTable("Activities"); + + b.HasDiscriminator("Discriminator").HasValue("Activity"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.ActivityPlayer", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActivityId") + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("ActivityId"); + + b.ToTable("ActivityPlayers"); + + b.HasDiscriminator("Discriminator").HasValue("ActivityPlayer"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.StagedActivity", b => + { + b.HasBaseType("Cocotte.Modules.Activity.Models.Activity"); + + b.Property("Stage") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("StagedActivity"); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.ActivityRolePlayer", b => + { + b.HasBaseType("Cocotte.Modules.Activity.Models.ActivityPlayer"); + + b.Property("Roles") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("ActivityRolePlayer"); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.ActivityPlayer", b => + { + b.HasOne("Cocotte.Modules.Activity.Models.Activity", "Activity") + .WithMany("ActivityPlayers") + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.Activity", b => + { + b.Navigation("ActivityPlayers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Cocotte/Migrations/20230320145030_InitialCreate.cs b/Cocotte/Migrations/20230320145030_InitialCreate.cs new file mode 100644 index 0000000..5dc3fcc --- /dev/null +++ b/Cocotte/Migrations/20230320145030_InitialCreate.cs @@ -0,0 +1,70 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Cocotte.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Activities", + columns: table => new + { + ActivityId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatorId = table.Column(type: "INTEGER", nullable: false), + Description = table.Column(type: "TEXT", nullable: true), + ActivityType = table.Column(type: "INTEGER", nullable: false), + ActivityName = table.Column(type: "INTEGER", nullable: false), + MaxPlayers = table.Column(type: "INTEGER", nullable: false), + Discriminator = table.Column(type: "TEXT", nullable: false), + Stage = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Activities", x => x.ActivityId); + }); + + migrationBuilder.CreateTable( + name: "ActivityPlayers", + columns: table => new + { + UserId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PlayerName = table.Column(type: "TEXT", nullable: false), + ActivityId = table.Column(type: "INTEGER", nullable: false), + Discriminator = table.Column(type: "TEXT", nullable: false), + Roles = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ActivityPlayers", x => x.UserId); + table.ForeignKey( + name: "FK_ActivityPlayers_Activities_ActivityId", + column: x => x.ActivityId, + principalTable: "Activities", + principalColumn: "ActivityId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ActivityPlayers_ActivityId", + table: "ActivityPlayers", + column: "ActivityId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ActivityPlayers"); + + migrationBuilder.DropTable( + name: "Activities"); + } + } +} diff --git a/Cocotte/Migrations/CocotteContextModelSnapshot.cs b/Cocotte/Migrations/CocotteContextModelSnapshot.cs new file mode 100644 index 0000000..a22a5e9 --- /dev/null +++ b/Cocotte/Migrations/CocotteContextModelSnapshot.cs @@ -0,0 +1,119 @@ +// +using Cocotte.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Cocotte.Migrations +{ + [DbContext(typeof(CocotteContext))] + partial class CocotteContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.Activity", b => + { + b.Property("ActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActivityName") + .HasColumnType("INTEGER"); + + b.Property("ActivityType") + .HasColumnType("INTEGER"); + + b.Property("CreatorId") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("MaxPlayers") + .HasColumnType("INTEGER"); + + b.HasKey("ActivityId"); + + b.ToTable("Activities"); + + b.HasDiscriminator("Discriminator").HasValue("Activity"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.ActivityPlayer", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActivityId") + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("ActivityId"); + + b.ToTable("ActivityPlayers"); + + b.HasDiscriminator("Discriminator").HasValue("ActivityPlayer"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.StagedActivity", b => + { + b.HasBaseType("Cocotte.Modules.Activity.Models.Activity"); + + b.Property("Stage") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("StagedActivity"); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.ActivityRolePlayer", b => + { + b.HasBaseType("Cocotte.Modules.Activity.Models.ActivityPlayer"); + + b.Property("Roles") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("ActivityRolePlayer"); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.ActivityPlayer", b => + { + b.HasOne("Cocotte.Modules.Activity.Models.Activity", "Activity") + .WithMany("ActivityPlayers") + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Cocotte.Modules.Activity.Models.Activity", b => + { + b.Navigation("ActivityPlayers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Cocotte/Modules/Activity/Activity.cs b/Cocotte/Modules/Activity/Activity.cs deleted file mode 100644 index 2bf01ad..0000000 --- a/Cocotte/Modules/Activity/Activity.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Cocotte.Modules.Activity; - -public abstract record Activity(ulong Owner, string Description, ActivityType ActivityType, ActivityName ActivityName, uint MaxPlayers); diff --git a/Cocotte/Modules/Activity/ActivityModule.cs b/Cocotte/Modules/Activity/ActivityModule.cs index b295c2f..79915fc 100644 --- a/Cocotte/Modules/Activity/ActivityModule.cs +++ b/Cocotte/Modules/Activity/ActivityModule.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Cocotte.Modules.Activity.Models; using Cocotte.Options; using Cocotte.Utils; using Discord; @@ -18,11 +19,13 @@ public class ActivityModule : InteractionModuleBase private readonly ILogger _logger; private readonly ActivityOptions _options; private readonly ActivityHelper _activityHelper; + private readonly ActivitiesRepository _activitiesRepository; - public ActivityModule(ILogger logger, IOptions options, ActivityHelper activityHelper) + public ActivityModule(ILogger logger, IOptions options, ActivityHelper activityHelper, ActivitiesRepository activitiesRepository) { _logger = logger; _activityHelper = activityHelper; + _activitiesRepository = activitiesRepository; _options = options.Value; } @@ -39,19 +42,28 @@ public class ActivityModule : InteractionModuleBase } [SlashCommand("abyss", "Créer un groupe pour l'Abîme du Néant")] - public async Task GroupAbyss([Summary("étage", "A quel étage êtes vous")] uint stage, [Summary("description", "Message accompagnant la demande de groupe")] string description = "") + public async Task ActivityAbyss([Summary("étage", "A quel étage êtes vous")] uint stage, [Summary("description", "Message accompagnant la demande de groupe")] string description = "") { const ActivityName activityName = ActivityName.Abyss; var activityType = ActivityHelper.ActivityNameToType(activityName); var maxPlayers = ActivityHelper.ActivityTypeToMaxPlayers(activityType); - var activityId = Context.Interaction.Id; - var activity = new StagedActivity(Context.User.Id, description, activityType, activityName, maxPlayers, stage); + var activity = new StagedActivity + { + ActivityId = 0, + CreatorId = Context.User.Id, + Description = description, + ActivityType = activityType, + ActivityName = activityName, + MaxPlayers = maxPlayers, + Stage = stage, + ActivityPlayers = new() + }; - await CreateActivity(activity); + await CreateRoleActivity(activity); } - private async Task CreateActivity(Activity activity) + private async Task CreateRoleActivity(Models.Activity activity) { _logger.LogTrace("Creating activity {Activity}", activity); @@ -59,10 +71,13 @@ public class ActivityModule : InteractionModuleBase await RespondAsync("`Création de l'activité en cours...`"); var response = await GetOriginalResponseAsync(); - var activityId = response.Id; + activity.ActivityId = response.Id; + + // Add activity to db + await _activitiesRepository.AddActivity(activity); // Add components - var components = ActivityComponent(activityId); + var components = ActivityRoleComponent(activity.ActivityId); await ModifyOriginalResponseAsync(m => { @@ -72,15 +87,41 @@ public class ActivityModule : InteractionModuleBase }); } - [ComponentInteraction("activity join:*", ignoreGroupNames: true)] - private async Task JoinActivity(ulong activityId) + [ComponentInteraction("activity join_role:*", ignoreGroupNames: true)] + private async Task JoinActivityRole(ulong activityId) { var user = (SocketGuildUser)Context.User; + // Check if activity exists + if (await _activitiesRepository.FindActivity(activityId) is not { } activity) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed("Cette activité n'existe plus").Build() + ); + + return; + } + + // If player is already registered + if (await _activitiesRepository.FindActivityRolePlayer(activityId, user.Id) is not null) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed("Vous êtes déjà inscrit à cette activité").Build() + ); + + return; + } + _logger.LogTrace("Player {Player} joined activity {Id}", user.DisplayName, activityId); var roles = _activityHelper.GetPlayerRoles(user.Roles); - var activityPlayer = new ActivityRolePlayer(user.Id, user.DisplayName, roles); + var activityRolePlayer = new ActivityRolePlayer { UserId = user.Id, PlayerName = user.DisplayName, Roles = roles, ActivityId = activityId, Activity = activity }; + + // Add player to activity + activity.ActivityPlayers.Add(activityRolePlayer); + await _activitiesRepository.SaveChanges(); await RespondAsync( ephemeral: true, @@ -88,14 +129,37 @@ public class ActivityModule : InteractionModuleBase ); } - [ComponentInteraction("activity leave:*", ignoreGroupNames: true)] - private async Task LeaveActivity(ulong activityId) + [ComponentInteraction("activity leave_role:*", ignoreGroupNames: true)] + private async Task LeaveActivityRole(ulong activityId) { - var user = (SocketGuildUser)Context.User; + var user = (IGuildUser)Context.User; + + // Check if activity exists + if (await _activitiesRepository.FindActivity(activityId) is not { } activity) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed("Cette activité n'existe plus").Build() + ); + + return; + } + + // Check if player is in activity + if (await _activitiesRepository.FindActivityPlayer(activityId, user.Id) is not { } activityPlayer) + { + await RespondAsync( + ephemeral: true, + embed: EmbedUtils.ErrorEmbed("Vous n'êtes pas inscrit à cette activité").Build() + ); + + return; + } _logger.LogTrace("Player {Player} left activity {Id}", user.DisplayName, activityId); - // TODO: remove the user from the activity + activity.ActivityPlayers.Remove(activityPlayer); + await _activitiesRepository.SaveChanges(); await RespondAsync( ephemeral: true, @@ -106,23 +170,23 @@ public class ActivityModule : InteractionModuleBase [ComponentInteraction("activity event_join:*", ignoreGroupNames: true)] private async Task JoinEventActivity(ulong activityId) { - _logger.LogTrace("Player {Player} joined activity {Id}", ((SocketGuildUser)Context.User).DisplayName, activityId); + _logger.LogTrace("Player {Player} joined activity {Id}", ((IGuildUser)Context.User).DisplayName, activityId); await RespondAsync(activityId.ToString()); } - private static ComponentBuilder ActivityComponent(ulong activityId) + private static ComponentBuilder ActivityRoleComponent(ulong activityId) { return new ComponentBuilder() .AddRow(new ActionRowBuilder() .WithButton(new ButtonBuilder() .WithLabel("Rejoindre l'activité") - .WithCustomId($"activity join:{activityId}") + .WithCustomId($"activity join_role:{activityId}") .WithStyle(ButtonStyle.Primary) ) .WithButton(new ButtonBuilder() .WithLabel("Se désinscrire de l'activité") - .WithCustomId($"activity leave:{activityId}") + .WithCustomId($"activity leave_role:{activityId}") .WithStyle(ButtonStyle.Danger) ) ); diff --git a/Cocotte/Modules/Activity/ActivityPlayer.cs b/Cocotte/Modules/Activity/ActivityPlayer.cs deleted file mode 100644 index 8234862..0000000 --- a/Cocotte/Modules/Activity/ActivityPlayer.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Cocotte.Modules.Activity; - -public record ActivityPlayer(ulong UserId, string PlayerName); \ No newline at end of file diff --git a/Cocotte/Modules/Activity/ActivityRolePlayer.cs b/Cocotte/Modules/Activity/ActivityRolePlayer.cs deleted file mode 100644 index 407b678..0000000 --- a/Cocotte/Modules/Activity/ActivityRolePlayer.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Cocotte.Modules.Activity; - -public record ActivityRolePlayer(ulong UserId, string PlayerName, ActivityRoles Roles) : ActivityPlayer(UserId, PlayerName); \ No newline at end of file diff --git a/Cocotte/Modules/Activity/Models/ActivitiesRepository.cs b/Cocotte/Modules/Activity/Models/ActivitiesRepository.cs new file mode 100644 index 0000000..2aeeef4 --- /dev/null +++ b/Cocotte/Modules/Activity/Models/ActivitiesRepository.cs @@ -0,0 +1,45 @@ +using Cocotte.Services; +using Microsoft.EntityFrameworkCore; + +namespace Cocotte.Modules.Activity.Models; + +public class ActivitiesRepository +{ + private readonly CocotteContext _cocotteContext; + + public ActivitiesRepository(CocotteContext cocotteContext) + { + _cocotteContext = cocotteContext; + } + + public async Task FindActivity(ulong activityId) + { + return await _cocotteContext.Activities.FindAsync(activityId); + } + + public async Task FindStagedActivity(ulong activityId) + { + return await _cocotteContext.StagedActivities.FindAsync(activityId); + } + + public async Task FindActivityPlayer(ulong activityId, ulong playerId) + { + return await _cocotteContext.ActivityPlayers.FindAsync(activityId, playerId); + } + + public async Task FindActivityRolePlayer(ulong activityId, ulong playerId) + { + return await _cocotteContext.ActivityRolePlayers.FindAsync(activityId, playerId); + } + + public async Task AddActivity(Activity activity) + { + await _cocotteContext.AddAsync(activity); + await _cocotteContext.SaveChangesAsync(); + } + + public async Task SaveChanges() + { + await _cocotteContext.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/Cocotte/Modules/Activity/Models/Activity.cs b/Cocotte/Modules/Activity/Models/Activity.cs new file mode 100644 index 0000000..366e119 --- /dev/null +++ b/Cocotte/Modules/Activity/Models/Activity.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; + +namespace Cocotte.Modules.Activity.Models; + +public abstract class Activity +{ + [Key] + public ulong ActivityId { get; set; } + + public ulong CreatorId { get; init; } + public string? Description { get; init; } + public ActivityType ActivityType { get; init; } + public ActivityName ActivityName { get; init; } + public uint MaxPlayers { get; set; } + + public List ActivityPlayers { get; init; } = new(); + + public override string ToString() + { + return $"{nameof(ActivityId)}: {ActivityId}, {nameof(CreatorId)}: {CreatorId}, {nameof(Description)}: {Description}, {nameof(ActivityType)}: {ActivityType}, {nameof(ActivityName)}: {ActivityName}, {nameof(MaxPlayers)}: {MaxPlayers}"; + } +} \ No newline at end of file diff --git a/Cocotte/Modules/Activity/Models/ActivityPlayer.cs b/Cocotte/Modules/Activity/Models/ActivityPlayer.cs new file mode 100644 index 0000000..25579f8 --- /dev/null +++ b/Cocotte/Modules/Activity/Models/ActivityPlayer.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; + +namespace Cocotte.Modules.Activity.Models; + +[PrimaryKey(nameof(ActivityId), nameof(UserId))] +public class ActivityPlayer +{ + public ulong UserId { get; init; } + + public required string PlayerName { get; init; } + + public ulong ActivityId { get; init; } + public required Activity Activity { get; init; } + + public override string ToString() + { + return $"{nameof(UserId)}: {UserId}, {nameof(PlayerName)}: {PlayerName}"; + } +} \ No newline at end of file diff --git a/Cocotte/Modules/Activity/Models/ActivityRolePlayer.cs b/Cocotte/Modules/Activity/Models/ActivityRolePlayer.cs new file mode 100644 index 0000000..c325230 --- /dev/null +++ b/Cocotte/Modules/Activity/Models/ActivityRolePlayer.cs @@ -0,0 +1,6 @@ +namespace Cocotte.Modules.Activity.Models; + +public class ActivityRolePlayer : ActivityPlayer +{ + public required ActivityRoles Roles { get; init; } +} \ No newline at end of file diff --git a/Cocotte/Modules/Activity/Models/StagedActivity.cs b/Cocotte/Modules/Activity/Models/StagedActivity.cs new file mode 100644 index 0000000..789f765 --- /dev/null +++ b/Cocotte/Modules/Activity/Models/StagedActivity.cs @@ -0,0 +1,11 @@ +namespace Cocotte.Modules.Activity.Models; + +public class StagedActivity : Activity +{ + public uint Stage { get; set; } + + public override string ToString() + { + return $"{base.ToString()}, {nameof(Stage)}: {Stage}"; + } +} \ No newline at end of file diff --git a/Cocotte/Modules/Activity/StagedActivity.cs b/Cocotte/Modules/Activity/StagedActivity.cs deleted file mode 100644 index 5537349..0000000 --- a/Cocotte/Modules/Activity/StagedActivity.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Cocotte.Modules.Activity; - -public record StagedActivity(ulong Owner, string Description, ActivityType ActivityType, ActivityName ActivityName, uint MaxPlayers, uint Stage) - : Activity(Owner, Description, ActivityType, ActivityName, MaxPlayers); \ No newline at end of file diff --git a/Cocotte/Program.cs b/Cocotte/Program.cs index 31045d2..1fd388a 100644 --- a/Cocotte/Program.cs +++ b/Cocotte/Program.cs @@ -1,4 +1,5 @@ using Cocotte.Modules.Activity; +using Cocotte.Modules.Activity.Models; using Cocotte.Modules.Raids; using Cocotte.Options; using Cocotte.Services; @@ -6,6 +7,7 @@ using Discord; using Discord.Commands; using Discord.Interactions; using Discord.WebSocket; +using Microsoft.EntityFrameworkCore; DiscordSocketConfig discordSocketConfig = new() { @@ -26,6 +28,11 @@ IHost host = Host.CreateDefaultBuilder(args) services.Configure(context.Configuration.GetSection(DiscordOptions.SectionName)); services.Configure(context.Configuration.GetSection(ActivityOptions.SectionName)); + // Database + services.AddDbContext(options => + options.UseSqlite(context.Configuration.GetConnectionString("CocotteContext")), ServiceLifetime.Transient, ServiceLifetime.Transient); + services.AddTransient(); + // Discord.Net services.AddHostedService(); diff --git a/Cocotte/Services/CocotteContext.cs b/Cocotte/Services/CocotteContext.cs new file mode 100644 index 0000000..f64327c --- /dev/null +++ b/Cocotte/Services/CocotteContext.cs @@ -0,0 +1,18 @@ +using Cocotte.Modules.Activity.Models; +using Microsoft.EntityFrameworkCore; + +namespace Cocotte.Services; + +public class CocotteContext : DbContext +{ + public DbSet Activities => Set(); + public DbSet StagedActivities => Set(); + + public DbSet ActivityPlayers => Set(); + public DbSet ActivityRolePlayers => Set(); + + public CocotteContext(DbContextOptions options) : base(options) + { + + } +} \ No newline at end of file diff --git a/Cocotte/appsettings.json b/Cocotte/appsettings.json index b2dcdb6..8e13436 100644 --- a/Cocotte/appsettings.json +++ b/Cocotte/appsettings.json @@ -4,5 +4,8 @@ "Default": "Information", "Microsoft.Hosting.Lifetime": "Information" } + }, + "ConnectionStrings": { + "CocotteContext": "Data Source=cocotte.db" } } diff --git a/Cocotte/cocotte.db b/Cocotte/cocotte.db new file mode 100644 index 0000000..980611f Binary files /dev/null and b/Cocotte/cocotte.db differ